@fragments-sdk/ui 0.9.6 → 0.9.7
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/codeblock.cjs +25 -29
- package/dist/codeblock.cjs.map +1 -1
- package/dist/codeblock.js +25 -29
- package/dist/codeblock.js.map +1 -1
- package/dist/components/Chip/index.cjs +2 -1
- package/dist/components/Chip/index.cjs.map +1 -1
- package/dist/components/Chip/index.d.ts.map +1 -1
- package/dist/components/Chip/index.js +2 -1
- package/dist/components/Chip/index.js.map +1 -1
- package/dist/components/CodeBlock/index.d.ts.map +1 -1
- package/dist/components/Command/index.cjs +6 -0
- package/dist/components/Command/index.cjs.map +1 -1
- package/dist/components/Command/index.d.ts.map +1 -1
- package/dist/components/Command/index.js +6 -0
- package/dist/components/Command/index.js.map +1 -1
- package/dist/components/DataTable/index.cjs +26 -26
- package/dist/components/DataTable/index.cjs.map +1 -1
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +26 -26
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/Listbox/index.cjs +6 -0
- package/dist/components/Listbox/index.cjs.map +1 -1
- package/dist/components/Listbox/index.d.ts.map +1 -1
- package/dist/components/Listbox/index.js +6 -0
- package/dist/components/Listbox/index.js.map +1 -1
- package/dist/components/Loading/index.cjs +2 -12
- package/dist/components/Loading/index.cjs.map +1 -1
- package/dist/components/Loading/index.d.ts.map +1 -1
- package/dist/components/Loading/index.js +2 -12
- package/dist/components/Loading/index.js.map +1 -1
- package/dist/components/NavigationMenu/index.cjs +12 -1
- package/dist/components/NavigationMenu/index.cjs.map +1 -1
- package/dist/components/NavigationMenu/index.d.ts.map +1 -1
- package/dist/components/NavigationMenu/index.js +12 -1
- package/dist/components/NavigationMenu/index.js.map +1 -1
- package/dist/components/Skeleton/index.cjs +3 -3
- package/dist/components/Skeleton/index.cjs.map +1 -1
- package/dist/components/Skeleton/index.js +3 -3
- package/dist/components/Skeleton/index.js.map +1 -1
- package/dist/components/Stack/index.cjs +4 -3
- package/dist/components/Stack/index.cjs.map +1 -1
- package/dist/components/Stack/index.d.ts.map +1 -1
- package/dist/components/Stack/index.js +4 -3
- package/dist/components/Stack/index.js.map +1 -1
- package/dist/markdown.cjs +1 -1
- package/dist/markdown.cjs.map +1 -1
- package/dist/markdown.js +1 -1
- package/dist/markdown.js.map +1 -1
- package/fragments.json +1 -1
- package/package.json +1 -1
- package/src/components/Chip/index.tsx +3 -1
- package/src/components/CodeBlock/index.tsx +35 -41
- package/src/components/ColorPicker/ColorPicker.fragment.tsx +17 -15
- package/src/components/Command/index.tsx +1 -0
- package/src/components/DataTable/index.tsx +45 -45
- package/src/components/Listbox/index.tsx +1 -0
- package/src/components/Loading/index.tsx +6 -12
- package/src/components/Markdown/index.tsx +2 -2
- package/src/components/Menu/Menu.fragment.tsx +17 -15
- package/src/components/NavigationMenu/index.tsx +6 -1
- package/src/components/Skeleton/index.tsx +3 -3
- package/src/components/Slider/Slider.fragment.tsx +19 -17
- package/src/components/Stack/index.tsx +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,26 @@ function loadTableDeps() {
|
|
|
24
24
|
_tableFailed = true;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
function getColumnSizeStyle(column) {
|
|
28
|
+
const { size, minSize, maxSize } = column.columnDef;
|
|
29
|
+
const hasExplicitSize = size !== void 0 || minSize !== void 0 || maxSize !== void 0;
|
|
30
|
+
if (!hasExplicitSize) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
const resolvedSize = column.getSize();
|
|
34
|
+
return {
|
|
35
|
+
width: resolvedSize,
|
|
36
|
+
minWidth: minSize ?? resolvedSize,
|
|
37
|
+
maxWidth: maxSize ?? resolvedSize
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function isInteractiveTarget(target, currentTarget) {
|
|
41
|
+
if (!(target instanceof Element)) return false;
|
|
42
|
+
const interactiveElement = target.closest(
|
|
43
|
+
'button, a, input, select, textarea, [role="button"], [role="link"], [role="checkbox"], [role="switch"]'
|
|
44
|
+
);
|
|
45
|
+
return Boolean(interactiveElement && currentTarget.contains(interactiveElement));
|
|
46
|
+
}
|
|
27
47
|
function DataTableRoot({
|
|
28
48
|
columns: userColumns,
|
|
29
49
|
data,
|
|
@@ -91,6 +111,12 @@ function DataTableRoot({
|
|
|
91
111
|
};
|
|
92
112
|
return [checkboxColumn, ...userColumns];
|
|
93
113
|
}, [userColumns, showCheckbox, selectable]);
|
|
114
|
+
const hasExplicitColumnSizing = React.useMemo(
|
|
115
|
+
() => columns.some(
|
|
116
|
+
(column) => column.size !== void 0 || column.minSize !== void 0 || column.maxSize !== void 0
|
|
117
|
+
),
|
|
118
|
+
[columns]
|
|
119
|
+
);
|
|
94
120
|
if (_tableFailed || !_useReactTable) {
|
|
95
121
|
if (_tableFailed && process.env.NODE_ENV === "development") {
|
|
96
122
|
console.warn(
|
|
@@ -121,12 +147,6 @@ function DataTableRoot({
|
|
|
121
147
|
enableExpanding: hasSubRows
|
|
122
148
|
});
|
|
123
149
|
const isEmpty = data.length === 0;
|
|
124
|
-
const hasExplicitColumnSizing = React.useMemo(
|
|
125
|
-
() => columns.some(
|
|
126
|
-
(column) => column.size !== void 0 || column.minSize !== void 0 || column.maxSize !== void 0
|
|
127
|
-
),
|
|
128
|
-
[columns]
|
|
129
|
-
);
|
|
130
150
|
const rootClasses = [
|
|
131
151
|
styles.table,
|
|
132
152
|
hasExplicitColumnSizing && styles.fixedLayout,
|
|
@@ -134,29 +154,9 @@ function DataTableRoot({
|
|
|
134
154
|
striped && styles.striped,
|
|
135
155
|
className
|
|
136
156
|
].filter(Boolean).join(" ");
|
|
137
|
-
const getColumnSizeStyle = (column) => {
|
|
138
|
-
const { size: size2, minSize, maxSize } = column.columnDef;
|
|
139
|
-
const hasExplicitSize = size2 !== void 0 || minSize !== void 0 || maxSize !== void 0;
|
|
140
|
-
if (!hasExplicitSize) {
|
|
141
|
-
return void 0;
|
|
142
|
-
}
|
|
143
|
-
const resolvedSize = column.getSize();
|
|
144
|
-
return {
|
|
145
|
-
width: resolvedSize,
|
|
146
|
-
minWidth: minSize ?? resolvedSize,
|
|
147
|
-
maxWidth: maxSize ?? resolvedSize
|
|
148
|
-
};
|
|
149
|
-
};
|
|
150
157
|
if (isEmpty) {
|
|
151
158
|
return /* @__PURE__ */ jsx("div", { className: styles.emptyState, children: /* @__PURE__ */ jsx("span", { className: styles.emptyMessage, children: emptyMessage }) });
|
|
152
159
|
}
|
|
153
|
-
const isInteractiveTarget = (target, currentTarget) => {
|
|
154
|
-
if (!(target instanceof Element)) return false;
|
|
155
|
-
const interactiveElement = target.closest(
|
|
156
|
-
'button, a, input, select, textarea, [role="button"], [role="link"], [role="checkbox"], [role="switch"]'
|
|
157
|
-
);
|
|
158
|
-
return Boolean(interactiveElement && currentTarget.contains(interactiveElement));
|
|
159
|
-
};
|
|
160
160
|
return /* @__PURE__ */ jsx("div", { className: [styles.wrapper, bordered && styles.bordered].filter(Boolean).join(" "), children: /* @__PURE__ */ jsxs(
|
|
161
161
|
"table",
|
|
162
162
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/DataTable/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n// Import globals to ensure CSS variables are defined\nimport '../../styles/globals.scss';\nimport styles from './DataTable.module.scss';\nimport { Checkbox } from '../Checkbox';\n\n// ============================================\n// Types (self-owned — no external dependency for types)\n// ============================================\n\n/** Column definition compatible with @tanstack/react-table */\nexport type ColumnDef<TData = unknown, TValue = unknown> = {\n id?: string;\n accessorKey?: string;\n accessorFn?: (row: TData) => TValue;\n header?: string | ((context: any) => React.ReactNode);\n cell?: string | ((context: any) => React.ReactNode);\n size?: number;\n minSize?: number;\n maxSize?: number;\n enableSorting?: boolean;\n [key: string]: unknown;\n};\n\nexport type SortingState = Array<{ id: string; desc: boolean }>;\nexport type RowSelectionState = Record<string, boolean>;\nexport type ExpandedState = true | Record<string, boolean>;\ntype OnChangeFn<T> = ((updaterOrValue: T | ((prev: T) => T)) => void);\n\nexport type DataTableColumn<T> = ColumnDef<T, unknown>;\n\n// ============================================\n// Lazy-loaded dependency (@tanstack/react-table)\n// ============================================\n\nlet _useReactTable: any = null;\nlet _getCoreRowModel: any = null;\nlet _getSortedRowModel: any = null;\nlet _getExpandedRowModel: any = null;\nlet _flexRender: any = null;\nlet _tableLoaded = false;\nlet _tableFailed = false;\n\nfunction loadTableDeps() {\n if (_tableLoaded) return;\n _tableLoaded = true;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const rt = require('@tanstack/react-table');\n _useReactTable = rt.useReactTable;\n _getCoreRowModel = rt.getCoreRowModel;\n _getSortedRowModel = rt.getSortedRowModel;\n _getExpandedRowModel = rt.getExpandedRowModel;\n _flexRender = rt.flexRender;\n } catch {\n _tableFailed = true;\n }\n}\n\nexport interface DataTableProps<T> extends Omit<React.HTMLAttributes<HTMLTableElement>, 'onClick'> {\n /** Column definitions */\n columns: DataTableColumn<T>[];\n /** Data array */\n data: T[];\n /** Unique key extractor for each row */\n getRowId?: (row: T) => string;\n /** Enable sorting */\n sortable?: boolean;\n /** Controlled sorting state */\n sorting?: SortingState;\n /** Sorting change handler */\n onSortingChange?: OnChangeFn<SortingState>;\n /** Enable row selection */\n selectable?: boolean;\n /** Show checkbox column for row selection */\n showCheckbox?: boolean;\n /** Controlled selection state */\n rowSelection?: RowSelectionState;\n /** Selection change handler */\n onRowSelectionChange?: OnChangeFn<RowSelectionState>;\n /** Row click handler */\n onRowClick?: (row: T) => void;\n /** Extract sub-rows from a row for expandable tree tables */\n getSubRows?: (row: T) => T[] | undefined;\n /** Controlled expanded state */\n expanded?: ExpandedState;\n /** Expanded state change handler */\n onExpandedChange?: OnChangeFn<ExpandedState>;\n /** Empty state message */\n emptyMessage?: string;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Visible caption for the table (recommended for accessibility) */\n caption?: string;\n /** Hide the caption visually but keep it for screen readers */\n captionHidden?: boolean;\n /** Show alternating row backgrounds */\n striped?: boolean;\n /** Wrap table in a bordered container */\n bordered?: boolean;\n}\n\nfunction DataTableRoot<T>({\n columns: userColumns,\n data,\n getRowId,\n sortable = false,\n sorting: controlledSorting,\n onSortingChange,\n selectable = false,\n showCheckbox = false,\n rowSelection: controlledRowSelection,\n onRowSelectionChange,\n onRowClick,\n getSubRows,\n expanded: controlledExpanded,\n onExpandedChange,\n emptyMessage = 'No data available',\n size = 'md',\n className,\n caption,\n captionHidden = false,\n striped = false,\n bordered = false,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedBy,\n ...htmlProps\n}: DataTableProps<T>) {\n loadTableDeps();\n\n // Internal sorting state when uncontrolled\n const [internalSorting, setInternalSorting] = React.useState<SortingState>([]);\n const sorting = controlledSorting ?? internalSorting;\n const handleSortingChange = onSortingChange ?? setInternalSorting;\n\n // Internal selection state when uncontrolled\n const [internalRowSelection, setInternalRowSelection] = React.useState<RowSelectionState>({});\n const rowSelection = controlledRowSelection ?? internalRowSelection;\n const handleRowSelectionChange = onRowSelectionChange ?? setInternalRowSelection;\n\n // Internal expanded state when uncontrolled\n const [internalExpanded, setInternalExpanded] = React.useState<ExpandedState>({});\n const expanded = controlledExpanded ?? internalExpanded;\n const handleExpandedChange = onExpandedChange ?? setInternalExpanded;\n\n // Build columns with optional checkbox prepended\n const columns = React.useMemo(() => {\n if (!showCheckbox || !selectable) return userColumns;\n\n const checkboxColumn: DataTableColumn<T> = {\n id: '__checkbox',\n size: 40,\n minSize: 40,\n maxSize: 40,\n enableSorting: false,\n header: ({ table }: any) => (\n <Checkbox\n size=\"sm\"\n checked={table.getIsAllRowsSelected()}\n indeterminate={table.getIsSomeRowsSelected()}\n onCheckedChange={() => table.toggleAllRowsSelected()}\n aria-label=\"Select all rows\"\n />\n ),\n cell: ({ row }: any) => (\n <Checkbox\n size=\"sm\"\n checked={row.getIsSelected()}\n disabled={!row.getCanSelect()}\n onCheckedChange={() => row.toggleSelected()}\n aria-label={`Select row ${row.id}`}\n />\n ),\n };\n\n return [checkboxColumn, ...userColumns];\n }, [userColumns, showCheckbox, selectable]);\n\n if (_tableFailed || !_useReactTable) {\n if (_tableFailed && process.env.NODE_ENV === 'development') {\n console.warn(\n '[@fragments-sdk/ui] DataTable: @tanstack/react-table is not installed. ' +\n 'Install it with: npm install @tanstack/react-table'\n );\n }\n return null;\n }\n\n const hasSubRows = !!getSubRows;\n\n const table = _useReactTable({\n data,\n columns,\n getRowId,\n getSubRows: getSubRows as any,\n getCoreRowModel: _getCoreRowModel(),\n getSortedRowModel: sortable ? _getSortedRowModel() : undefined,\n getExpandedRowModel: hasSubRows && _getExpandedRowModel ? _getExpandedRowModel() : undefined,\n state: {\n sorting: sortable ? sorting : undefined,\n rowSelection: selectable ? rowSelection : undefined,\n expanded: hasSubRows ? expanded : undefined,\n },\n onSortingChange: sortable ? handleSortingChange : undefined,\n onRowSelectionChange: selectable ? handleRowSelectionChange : undefined,\n onExpandedChange: hasSubRows ? handleExpandedChange : undefined,\n enableRowSelection: selectable,\n enableSorting: sortable,\n enableExpanding: hasSubRows,\n });\n\n const isEmpty = data.length === 0;\n\n const hasExplicitColumnSizing = React.useMemo(\n () =>\n columns.some((column) =>\n column.size !== undefined ||\n column.minSize !== undefined ||\n column.maxSize !== undefined\n ),\n [columns]\n );\n\n const rootClasses = [\n styles.table,\n hasExplicitColumnSizing && styles.fixedLayout,\n styles[size],\n striped && styles.striped,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const getColumnSizeStyle = (\n column: {\n getSize: () => number;\n columnDef: { size?: number; minSize?: number; maxSize?: number };\n }\n ): React.CSSProperties | undefined => {\n const { size, minSize, maxSize } = column.columnDef;\n const hasExplicitSize = size !== undefined || minSize !== undefined || maxSize !== undefined;\n\n if (!hasExplicitSize) {\n return undefined;\n }\n\n const resolvedSize = column.getSize();\n\n return {\n width: resolvedSize,\n minWidth: minSize ?? resolvedSize,\n maxWidth: maxSize ?? resolvedSize,\n };\n };\n\n if (isEmpty) {\n return (\n <div className={styles.emptyState}>\n <span className={styles.emptyMessage}>{emptyMessage}</span>\n </div>\n );\n }\n\n const isInteractiveTarget = (\n target: EventTarget | null,\n currentTarget: HTMLTableRowElement\n ) => {\n if (!(target instanceof Element)) return false;\n\n const interactiveElement = target.closest(\n 'button, a, input, select, textarea, [role=\"button\"], [role=\"link\"], [role=\"checkbox\"], [role=\"switch\"]'\n );\n\n return Boolean(interactiveElement && currentTarget.contains(interactiveElement));\n };\n\n return (\n <div className={[styles.wrapper, bordered && styles.bordered].filter(Boolean).join(' ')}>\n <table\n {...htmlProps}\n className={rootClasses}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n >\n {caption && (\n <caption className={captionHidden ? styles.captionHidden : styles.caption}>\n {caption}\n </caption>\n )}\n <thead className={styles.thead}>\n {table.getHeaderGroups().map((headerGroup: any) => (\n <tr key={headerGroup.id} className={styles.headerRow}>\n {headerGroup.headers.map((header: any) => {\n const canSort = sortable && header.column.getCanSort();\n const sortDirection = header.column.getIsSorted();\n const toggleSorting = canSort ? header.column.getToggleSortingHandler() : undefined;\n\n return (\n <th\n key={header.id}\n className={[styles.th, canSort && styles.thSortable].filter(Boolean).join(' ')}\n style={getColumnSizeStyle(header.column)}\n scope=\"col\"\n aria-sort={\n sortDirection\n ? sortDirection === 'asc'\n ? 'ascending'\n : 'descending'\n : canSort\n ? 'none'\n : undefined\n }\n >\n {canSort ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={toggleSorting}\n >\n <span className={styles.headerContent}>\n {header.isPlaceholder\n ? null\n : _flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </span>\n <span className={styles.sortIndicator} aria-hidden=\"true\">\n {sortDirection === 'asc' ? (\n <SortAscIcon />\n ) : sortDirection === 'desc' ? (\n <SortDescIcon />\n ) : (\n <SortIcon />\n )}\n </span>\n </button>\n ) : (\n <div className={styles.headerContent}>\n {header.isPlaceholder\n ? null\n : _flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </div>\n )}\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody className={styles.tbody}>\n {table.getRowModel().rows.map((row: any) => {\n const isClickable = !!onRowClick;\n const isSelected = selectable ? row.getIsSelected() : false;\n const depth: number = row.depth ?? 0;\n const canExpand = hasSubRows && row.getCanExpand();\n const handleRowClick = (event: React.MouseEvent<HTMLTableRowElement>) => {\n if (!onRowClick) return;\n if (isInteractiveTarget(event.target, event.currentTarget)) return;\n onRowClick(row.original);\n };\n\n const handleRowKeyDown = (event: React.KeyboardEvent<HTMLTableRowElement>) => {\n if (!onRowClick) return;\n if (isInteractiveTarget(event.target, event.currentTarget)) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onRowClick(row.original);\n }\n };\n\n return (\n <tr\n key={row.id}\n className={[\n styles.row,\n isClickable && styles.clickable,\n isSelected && styles.selected,\n depth > 0 && styles.subRow,\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={isClickable ? handleRowClick : undefined}\n onKeyDown={isClickable ? handleRowKeyDown : undefined}\n tabIndex={isClickable ? 0 : undefined}\n data-selected={isSelected || undefined}\n data-depth={depth > 0 ? depth : undefined}\n >\n {row.getVisibleCells().map((cell: any, cellIndex: number) => {\n const isFirstDataCell = hasSubRows && cellIndex === (showCheckbox && selectable ? 1 : 0);\n return (\n <td\n key={cell.id}\n className={styles.td}\n style={{\n ...getColumnSizeStyle(cell.column),\n ...(isFirstDataCell && depth > 0 ? { paddingLeft: `${depth * 24 + 12}px` } : undefined),\n }}\n >\n {isFirstDataCell && canExpand ? (\n <span className={styles.expandCell}>\n <button\n type=\"button\"\n className={styles.expandButton}\n onClick={row.getToggleExpandedHandler()}\n aria-label={row.getIsExpanded() ? 'Collapse row' : 'Expand row'}\n aria-expanded={row.getIsExpanded()}\n >\n <ExpandIcon expanded={row.getIsExpanded()} />\n </button>\n {_flexRender(cell.column.columnDef.cell, cell.getContext())}\n </span>\n ) : (\n _flexRender(cell.column.columnDef.cell, cell.getContext())\n )}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Expand/collapse icon for sub-rows\nfunction ExpandIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : undefined,\n transition: 'transform 150ms ease',\n }}\n >\n <path d=\"M4.5 2.5L8 6L4.5 9.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\n// Sort icons - minimal and functional\nfunction SortIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 2L8.5 5H3.5L6 2Z\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n />\n <path\n d=\"M6 10L3.5 7H8.5L6 10Z\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n />\n </svg>\n );\n}\n\nfunction SortAscIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 2L8.5 5H3.5L6 2Z\" fill=\"currentColor\" />\n </svg>\n );\n}\n\nfunction SortDescIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 10L3.5 7H8.5L6 10Z\" fill=\"currentColor\" />\n </svg>\n );\n}\n\n// Helper to create simple columns without TanStack's createColumnHelper\nexport function createColumns<T>(\n columns: Array<{\n key: string;\n header: string;\n width?: number;\n cell?: (row: T) => React.ReactNode;\n }>\n): DataTableColumn<T>[] {\n return columns.map((col) => ({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n size: col.width,\n minSize: col.width,\n maxSize: col.width,\n cell: col.cell\n ? ({ row }) => col.cell!(row.original)\n : ({ getValue }) => getValue() ?? '--',\n }));\n}\n\nexport const DataTable = Object.assign(DataTableRoot, {\n Root: DataTableRoot,\n Columns: createColumns,\n});\n"],"names":["table","size"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/DataTable/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n// Import globals to ensure CSS variables are defined\nimport '../../styles/globals.scss';\nimport styles from './DataTable.module.scss';\nimport { Checkbox } from '../Checkbox';\n\n// ============================================\n// Types (self-owned — no external dependency for types)\n// ============================================\n\n/** Column definition compatible with @tanstack/react-table */\nexport type ColumnDef<TData = unknown, TValue = unknown> = {\n id?: string;\n accessorKey?: string;\n accessorFn?: (row: TData) => TValue;\n header?: string | ((context: any) => React.ReactNode);\n cell?: string | ((context: any) => React.ReactNode);\n size?: number;\n minSize?: number;\n maxSize?: number;\n enableSorting?: boolean;\n [key: string]: unknown;\n};\n\nexport type SortingState = Array<{ id: string; desc: boolean }>;\nexport type RowSelectionState = Record<string, boolean>;\nexport type ExpandedState = true | Record<string, boolean>;\ntype OnChangeFn<T> = ((updaterOrValue: T | ((prev: T) => T)) => void);\n\nexport type DataTableColumn<T> = ColumnDef<T, unknown>;\n\n// ============================================\n// Lazy-loaded dependency (@tanstack/react-table)\n// ============================================\n\nlet _useReactTable: any = null;\nlet _getCoreRowModel: any = null;\nlet _getSortedRowModel: any = null;\nlet _getExpandedRowModel: any = null;\nlet _flexRender: any = null;\nlet _tableLoaded = false;\nlet _tableFailed = false;\n\nfunction loadTableDeps() {\n if (_tableLoaded) return;\n _tableLoaded = true;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const rt = require('@tanstack/react-table');\n _useReactTable = rt.useReactTable;\n _getCoreRowModel = rt.getCoreRowModel;\n _getSortedRowModel = rt.getSortedRowModel;\n _getExpandedRowModel = rt.getExpandedRowModel;\n _flexRender = rt.flexRender;\n } catch {\n _tableFailed = true;\n }\n}\n\nexport interface DataTableProps<T> extends Omit<React.HTMLAttributes<HTMLTableElement>, 'onClick'> {\n /** Column definitions */\n columns: DataTableColumn<T>[];\n /** Data array */\n data: T[];\n /** Unique key extractor for each row */\n getRowId?: (row: T) => string;\n /** Enable sorting */\n sortable?: boolean;\n /** Controlled sorting state */\n sorting?: SortingState;\n /** Sorting change handler */\n onSortingChange?: OnChangeFn<SortingState>;\n /** Enable row selection */\n selectable?: boolean;\n /** Show checkbox column for row selection */\n showCheckbox?: boolean;\n /** Controlled selection state */\n rowSelection?: RowSelectionState;\n /** Selection change handler */\n onRowSelectionChange?: OnChangeFn<RowSelectionState>;\n /** Row click handler */\n onRowClick?: (row: T) => void;\n /** Extract sub-rows from a row for expandable tree tables */\n getSubRows?: (row: T) => T[] | undefined;\n /** Controlled expanded state */\n expanded?: ExpandedState;\n /** Expanded state change handler */\n onExpandedChange?: OnChangeFn<ExpandedState>;\n /** Empty state message */\n emptyMessage?: string;\n /** Size variant */\n size?: 'sm' | 'md';\n /** Visible caption for the table (recommended for accessibility) */\n caption?: string;\n /** Hide the caption visually but keep it for screen readers */\n captionHidden?: boolean;\n /** Show alternating row backgrounds */\n striped?: boolean;\n /** Wrap table in a bordered container */\n bordered?: boolean;\n}\n\nfunction getColumnSizeStyle(\n column: {\n getSize: () => number;\n columnDef: { size?: number; minSize?: number; maxSize?: number };\n }\n): React.CSSProperties | undefined {\n const { size, minSize, maxSize } = column.columnDef;\n const hasExplicitSize = size !== undefined || minSize !== undefined || maxSize !== undefined;\n\n if (!hasExplicitSize) {\n return undefined;\n }\n\n const resolvedSize = column.getSize();\n\n return {\n width: resolvedSize,\n minWidth: minSize ?? resolvedSize,\n maxWidth: maxSize ?? resolvedSize,\n };\n}\n\nfunction isInteractiveTarget(\n target: EventTarget | null,\n currentTarget: HTMLTableRowElement\n) {\n if (!(target instanceof Element)) return false;\n\n const interactiveElement = target.closest(\n 'button, a, input, select, textarea, [role=\"button\"], [role=\"link\"], [role=\"checkbox\"], [role=\"switch\"]'\n );\n\n return Boolean(interactiveElement && currentTarget.contains(interactiveElement));\n}\n\nfunction DataTableRoot<T>({\n columns: userColumns,\n data,\n getRowId,\n sortable = false,\n sorting: controlledSorting,\n onSortingChange,\n selectable = false,\n showCheckbox = false,\n rowSelection: controlledRowSelection,\n onRowSelectionChange,\n onRowClick,\n getSubRows,\n expanded: controlledExpanded,\n onExpandedChange,\n emptyMessage = 'No data available',\n size = 'md',\n className,\n caption,\n captionHidden = false,\n striped = false,\n bordered = false,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedBy,\n ...htmlProps\n}: DataTableProps<T>) {\n loadTableDeps();\n\n // Internal sorting state when uncontrolled\n const [internalSorting, setInternalSorting] = React.useState<SortingState>([]);\n const sorting = controlledSorting ?? internalSorting;\n const handleSortingChange = onSortingChange ?? setInternalSorting;\n\n // Internal selection state when uncontrolled\n const [internalRowSelection, setInternalRowSelection] = React.useState<RowSelectionState>({});\n const rowSelection = controlledRowSelection ?? internalRowSelection;\n const handleRowSelectionChange = onRowSelectionChange ?? setInternalRowSelection;\n\n // Internal expanded state when uncontrolled\n const [internalExpanded, setInternalExpanded] = React.useState<ExpandedState>({});\n const expanded = controlledExpanded ?? internalExpanded;\n const handleExpandedChange = onExpandedChange ?? setInternalExpanded;\n\n // Build columns with optional checkbox prepended\n const columns = React.useMemo(() => {\n if (!showCheckbox || !selectable) return userColumns;\n\n const checkboxColumn: DataTableColumn<T> = {\n id: '__checkbox',\n size: 40,\n minSize: 40,\n maxSize: 40,\n enableSorting: false,\n header: ({ table }: any) => (\n <Checkbox\n size=\"sm\"\n checked={table.getIsAllRowsSelected()}\n indeterminate={table.getIsSomeRowsSelected()}\n onCheckedChange={() => table.toggleAllRowsSelected()}\n aria-label=\"Select all rows\"\n />\n ),\n cell: ({ row }: any) => (\n <Checkbox\n size=\"sm\"\n checked={row.getIsSelected()}\n disabled={!row.getCanSelect()}\n onCheckedChange={() => row.toggleSelected()}\n aria-label={`Select row ${row.id}`}\n />\n ),\n };\n\n return [checkboxColumn, ...userColumns];\n }, [userColumns, showCheckbox, selectable]);\n\n const hasExplicitColumnSizing = React.useMemo(\n () =>\n columns.some((column) =>\n column.size !== undefined ||\n column.minSize !== undefined ||\n column.maxSize !== undefined\n ),\n [columns]\n );\n\n if (_tableFailed || !_useReactTable) {\n if (_tableFailed && process.env.NODE_ENV === 'development') {\n console.warn(\n '[@fragments-sdk/ui] DataTable: @tanstack/react-table is not installed. ' +\n 'Install it with: npm install @tanstack/react-table'\n );\n }\n return null;\n }\n\n const hasSubRows = !!getSubRows;\n\n const table = _useReactTable({\n data,\n columns,\n getRowId,\n getSubRows: getSubRows as any,\n getCoreRowModel: _getCoreRowModel(),\n getSortedRowModel: sortable ? _getSortedRowModel() : undefined,\n getExpandedRowModel: hasSubRows && _getExpandedRowModel ? _getExpandedRowModel() : undefined,\n state: {\n sorting: sortable ? sorting : undefined,\n rowSelection: selectable ? rowSelection : undefined,\n expanded: hasSubRows ? expanded : undefined,\n },\n onSortingChange: sortable ? handleSortingChange : undefined,\n onRowSelectionChange: selectable ? handleRowSelectionChange : undefined,\n onExpandedChange: hasSubRows ? handleExpandedChange : undefined,\n enableRowSelection: selectable,\n enableSorting: sortable,\n enableExpanding: hasSubRows,\n });\n\n const isEmpty = data.length === 0;\n\n const rootClasses = [\n styles.table,\n hasExplicitColumnSizing && styles.fixedLayout,\n styles[size],\n striped && styles.striped,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n if (isEmpty) {\n return (\n <div className={styles.emptyState}>\n <span className={styles.emptyMessage}>{emptyMessage}</span>\n </div>\n );\n }\n\n return (\n <div className={[styles.wrapper, bordered && styles.bordered].filter(Boolean).join(' ')}>\n <table\n {...htmlProps}\n className={rootClasses}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n >\n {caption && (\n <caption className={captionHidden ? styles.captionHidden : styles.caption}>\n {caption}\n </caption>\n )}\n <thead className={styles.thead}>\n {table.getHeaderGroups().map((headerGroup: any) => (\n <tr key={headerGroup.id} className={styles.headerRow}>\n {headerGroup.headers.map((header: any) => {\n const canSort = sortable && header.column.getCanSort();\n const sortDirection = header.column.getIsSorted();\n const toggleSorting = canSort ? header.column.getToggleSortingHandler() : undefined;\n\n return (\n <th\n key={header.id}\n className={[styles.th, canSort && styles.thSortable].filter(Boolean).join(' ')}\n style={getColumnSizeStyle(header.column)}\n scope=\"col\"\n aria-sort={\n sortDirection\n ? sortDirection === 'asc'\n ? 'ascending'\n : 'descending'\n : canSort\n ? 'none'\n : undefined\n }\n >\n {canSort ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={toggleSorting}\n >\n <span className={styles.headerContent}>\n {header.isPlaceholder\n ? null\n : _flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </span>\n <span className={styles.sortIndicator} aria-hidden=\"true\">\n {sortDirection === 'asc' ? (\n <SortAscIcon />\n ) : sortDirection === 'desc' ? (\n <SortDescIcon />\n ) : (\n <SortIcon />\n )}\n </span>\n </button>\n ) : (\n <div className={styles.headerContent}>\n {header.isPlaceholder\n ? null\n : _flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </div>\n )}\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody className={styles.tbody}>\n {table.getRowModel().rows.map((row: any) => {\n const isClickable = !!onRowClick;\n const isSelected = selectable ? row.getIsSelected() : false;\n const depth: number = row.depth ?? 0;\n const canExpand = hasSubRows && row.getCanExpand();\n const handleRowClick = (event: React.MouseEvent<HTMLTableRowElement>) => {\n if (!onRowClick) return;\n if (isInteractiveTarget(event.target, event.currentTarget)) return;\n onRowClick(row.original);\n };\n\n const handleRowKeyDown = (event: React.KeyboardEvent<HTMLTableRowElement>) => {\n if (!onRowClick) return;\n if (isInteractiveTarget(event.target, event.currentTarget)) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onRowClick(row.original);\n }\n };\n\n return (\n <tr\n key={row.id}\n className={[\n styles.row,\n isClickable && styles.clickable,\n isSelected && styles.selected,\n depth > 0 && styles.subRow,\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={isClickable ? handleRowClick : undefined}\n onKeyDown={isClickable ? handleRowKeyDown : undefined}\n tabIndex={isClickable ? 0 : undefined}\n data-selected={isSelected || undefined}\n data-depth={depth > 0 ? depth : undefined}\n >\n {row.getVisibleCells().map((cell: any, cellIndex: number) => {\n const isFirstDataCell = hasSubRows && cellIndex === (showCheckbox && selectable ? 1 : 0);\n return (\n <td\n key={cell.id}\n className={styles.td}\n style={{\n ...getColumnSizeStyle(cell.column),\n ...(isFirstDataCell && depth > 0 ? { paddingLeft: `${depth * 24 + 12}px` } : undefined),\n }}\n >\n {isFirstDataCell && canExpand ? (\n <span className={styles.expandCell}>\n <button\n type=\"button\"\n className={styles.expandButton}\n onClick={row.getToggleExpandedHandler()}\n aria-label={row.getIsExpanded() ? 'Collapse row' : 'Expand row'}\n aria-expanded={row.getIsExpanded()}\n >\n <ExpandIcon expanded={row.getIsExpanded()} />\n </button>\n {_flexRender(cell.column.columnDef.cell, cell.getContext())}\n </span>\n ) : (\n _flexRender(cell.column.columnDef.cell, cell.getContext())\n )}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Expand/collapse icon for sub-rows\nfunction ExpandIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n style={{\n transform: expanded ? 'rotate(90deg)' : undefined,\n transition: 'transform 150ms ease',\n }}\n >\n <path d=\"M4.5 2.5L8 6L4.5 9.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\n\n// Sort icons - minimal and functional\nfunction SortIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 2L8.5 5H3.5L6 2Z\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n />\n <path\n d=\"M6 10L3.5 7H8.5L6 10Z\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n />\n </svg>\n );\n}\n\nfunction SortAscIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 2L8.5 5H3.5L6 2Z\" fill=\"currentColor\" />\n </svg>\n );\n}\n\nfunction SortDescIcon() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path d=\"M6 10L3.5 7H8.5L6 10Z\" fill=\"currentColor\" />\n </svg>\n );\n}\n\n// Helper to create simple columns without TanStack's createColumnHelper\nexport function createColumns<T>(\n columns: Array<{\n key: string;\n header: string;\n width?: number;\n cell?: (row: T) => React.ReactNode;\n }>\n): DataTableColumn<T>[] {\n return columns.map((col) => ({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n size: col.width,\n minSize: col.width,\n maxSize: col.width,\n cell: col.cell\n ? ({ row }) => col.cell!(row.original)\n : ({ getValue }) => getValue() ?? '--',\n }));\n}\n\nexport const DataTable = Object.assign(DataTableRoot, {\n Root: DataTableRoot,\n Columns: createColumns,\n});\n"],"names":["table"],"mappings":"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"}
|
|
@@ -186,6 +186,12 @@ function ListboxItem({
|
|
|
186
186
|
"aria-disabled": disabled,
|
|
187
187
|
"data-active": (context == null ? void 0 : context.activeId) === itemId || void 0,
|
|
188
188
|
onClick: disabled ? void 0 : onClick,
|
|
189
|
+
onKeyDown: disabled ? void 0 : (e) => {
|
|
190
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
191
|
+
e.preventDefault();
|
|
192
|
+
onClick == null ? void 0 : onClick();
|
|
193
|
+
}
|
|
194
|
+
},
|
|
189
195
|
onMouseEnter: handleMouseEnter,
|
|
190
196
|
className: classes,
|
|
191
197
|
style,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/Listbox/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Listbox.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ListboxProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport interface ListboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClick'> {\n children: React.ReactNode;\n /** Whether this item is currently selected/highlighted */\n selected?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport interface ListboxGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Group label */\n label?: string;\n}\n\nexport interface ListboxEmptyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\ninterface ListboxContextValue {\n activeId: string | null;\n setActiveId: (id: string | null) => void;\n}\n\nconst ListboxContext = React.createContext<ListboxContextValue | null>(null);\n\n// ============================================\n// Components\n// ============================================\n\nfunction ListboxRoot({\n children,\n className,\n style,\n 'aria-label': ariaLabel,\n tabIndex,\n onKeyDown,\n onFocus,\n ...htmlProps\n}: ListboxProps) {\n const classes = [styles.listbox, className].filter(Boolean).join(' ');\n const listboxRef = React.useRef<HTMLDivElement>(null);\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const getEnabledOptions = React.useCallback(() => {\n const listbox = listboxRef.current;\n if (!listbox) return [] as HTMLDivElement[];\n\n return Array.from(\n listbox.querySelectorAll<HTMLDivElement>('[role=\"option\"]')\n ).filter((option) => option.getAttribute('aria-disabled') !== 'true');\n }, []);\n\n const moveActive = React.useCallback(\n (direction: 'next' | 'prev' | 'first' | 'last') => {\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n if (direction === 'first') {\n setActiveId(options[0].id);\n return;\n }\n\n if (direction === 'last') {\n setActiveId(options[options.length - 1].id);\n return;\n }\n\n const currentIndex = activeId\n ? options.findIndex((option) => option.id === activeId)\n : -1;\n\n if (direction === 'next') {\n const nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % options.length;\n setActiveId(options[nextIndex].id);\n } else {\n const prevIndex = currentIndex < 0\n ? options.length - 1\n : (currentIndex - 1 + options.length) % options.length;\n setActiveId(options[prevIndex].id);\n }\n },\n [activeId, getEnabledOptions]\n );\n\n React.useEffect(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (!activeOption) return;\n\n const frame = window.requestAnimationFrame(() => {\n activeOption.scrollIntoView({ block: 'nearest' });\n });\n\n return () => {\n window.cancelAnimationFrame(frame);\n };\n }, [activeId]);\n\n const selectActiveItem = React.useCallback(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (activeOption && activeOption.getAttribute('aria-disabled') !== 'true') {\n activeOption.click();\n }\n }, [activeId]);\n\n const setDefaultActiveIfNeeded = React.useCallback(() => {\n if (activeId) return;\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n const selectedOption = options.find((option) => option.getAttribute('aria-selected') === 'true');\n setActiveId((selectedOption ?? options[0]).id);\n }, [activeId, getEnabledOptions]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveActive('next');\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveActive('prev');\n break;\n case 'Home':\n event.preventDefault();\n moveActive('first');\n break;\n case 'End':\n event.preventDefault();\n moveActive('last');\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n selectActiveItem();\n break;\n default:\n break;\n }\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n setDefaultActiveIfNeeded();\n onFocus?.(event);\n };\n\n const contextValue = React.useMemo<ListboxContextValue>(\n () => ({\n activeId,\n setActiveId,\n }),\n [activeId]\n );\n\n return (\n <ListboxContext.Provider value={contextValue}>\n <div\n ref={listboxRef}\n {...htmlProps}\n role=\"listbox\"\n aria-label={ariaLabel}\n aria-activedescendant={activeId ?? undefined}\n tabIndex={tabIndex ?? 0}\n className={classes}\n style={style}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n >\n {children}\n </div>\n </ListboxContext.Provider>\n );\n}\n\nfunction ListboxItem({\n children,\n selected = false,\n disabled = false,\n onClick,\n onMouseEnter,\n className,\n style,\n ...htmlProps\n}: ListboxItemProps) {\n const context = React.useContext(ListboxContext);\n const generatedId = React.useId();\n const itemId = (htmlProps.id as string | undefined) ?? `listbox-item-${generatedId}`;\n const classes = [\n styles.item,\n selected && styles.itemSelected,\n disabled && styles.itemDisabled,\n context?.activeId === itemId && styles.itemActive,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!disabled) {\n context?.setActiveId(itemId);\n }\n onMouseEnter?.(event);\n };\n\n return (\n <div\n {...htmlProps}\n id={itemId}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled}\n data-active={context?.activeId === itemId || undefined}\n onClick={disabled ? undefined : onClick}\n onMouseEnter={handleMouseEnter}\n className={classes}\n style={style}\n >\n {children}\n </div>\n );\n}\n\nfunction ListboxGroup({ children, label, className, ...htmlProps }: ListboxGroupProps) {\n const classes = [styles.group, className].filter(Boolean).join(' ');\n const labelId = React.useId();\n\n return (\n <div\n {...htmlProps}\n role=\"group\"\n aria-labelledby={label ? labelId : undefined}\n className={classes}\n >\n {label && <div id={labelId} className={styles.groupLabel}>{label}</div>}\n {children}\n </div>\n );\n}\n\nfunction ListboxEmpty({ children, className, ...htmlProps }: ListboxEmptyProps) {\n const classes = [styles.empty, className].filter(Boolean).join(' ');\n return (\n <div\n {...htmlProps}\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n className={classes}\n >\n {children}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Listbox = Object.assign(ListboxRoot, {\n Item: ListboxItem,\n Group: ListboxGroup,\n Empty: ListboxEmpty,\n});\n\n// Re-export individual components\nexport { ListboxRoot, ListboxItem, ListboxGroup, ListboxEmpty };\n"],"names":["React","styles","jsx","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/Listbox/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Listbox.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ListboxProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport interface ListboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClick'> {\n children: React.ReactNode;\n /** Whether this item is currently selected/highlighted */\n selected?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport interface ListboxGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Group label */\n label?: string;\n}\n\nexport interface ListboxEmptyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\ninterface ListboxContextValue {\n activeId: string | null;\n setActiveId: (id: string | null) => void;\n}\n\nconst ListboxContext = React.createContext<ListboxContextValue | null>(null);\n\n// ============================================\n// Components\n// ============================================\n\nfunction ListboxRoot({\n children,\n className,\n style,\n 'aria-label': ariaLabel,\n tabIndex,\n onKeyDown,\n onFocus,\n ...htmlProps\n}: ListboxProps) {\n const classes = [styles.listbox, className].filter(Boolean).join(' ');\n const listboxRef = React.useRef<HTMLDivElement>(null);\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const getEnabledOptions = React.useCallback(() => {\n const listbox = listboxRef.current;\n if (!listbox) return [] as HTMLDivElement[];\n\n return Array.from(\n listbox.querySelectorAll<HTMLDivElement>('[role=\"option\"]')\n ).filter((option) => option.getAttribute('aria-disabled') !== 'true');\n }, []);\n\n const moveActive = React.useCallback(\n (direction: 'next' | 'prev' | 'first' | 'last') => {\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n if (direction === 'first') {\n setActiveId(options[0].id);\n return;\n }\n\n if (direction === 'last') {\n setActiveId(options[options.length - 1].id);\n return;\n }\n\n const currentIndex = activeId\n ? options.findIndex((option) => option.id === activeId)\n : -1;\n\n if (direction === 'next') {\n const nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % options.length;\n setActiveId(options[nextIndex].id);\n } else {\n const prevIndex = currentIndex < 0\n ? options.length - 1\n : (currentIndex - 1 + options.length) % options.length;\n setActiveId(options[prevIndex].id);\n }\n },\n [activeId, getEnabledOptions]\n );\n\n React.useEffect(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (!activeOption) return;\n\n const frame = window.requestAnimationFrame(() => {\n activeOption.scrollIntoView({ block: 'nearest' });\n });\n\n return () => {\n window.cancelAnimationFrame(frame);\n };\n }, [activeId]);\n\n const selectActiveItem = React.useCallback(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (activeOption && activeOption.getAttribute('aria-disabled') !== 'true') {\n activeOption.click();\n }\n }, [activeId]);\n\n const setDefaultActiveIfNeeded = React.useCallback(() => {\n if (activeId) return;\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n const selectedOption = options.find((option) => option.getAttribute('aria-selected') === 'true');\n setActiveId((selectedOption ?? options[0]).id);\n }, [activeId, getEnabledOptions]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveActive('next');\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveActive('prev');\n break;\n case 'Home':\n event.preventDefault();\n moveActive('first');\n break;\n case 'End':\n event.preventDefault();\n moveActive('last');\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n selectActiveItem();\n break;\n default:\n break;\n }\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n setDefaultActiveIfNeeded();\n onFocus?.(event);\n };\n\n const contextValue = React.useMemo<ListboxContextValue>(\n () => ({\n activeId,\n setActiveId,\n }),\n [activeId]\n );\n\n return (\n <ListboxContext.Provider value={contextValue}>\n <div\n ref={listboxRef}\n {...htmlProps}\n role=\"listbox\"\n aria-label={ariaLabel}\n aria-activedescendant={activeId ?? undefined}\n tabIndex={tabIndex ?? 0}\n className={classes}\n style={style}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n >\n {children}\n </div>\n </ListboxContext.Provider>\n );\n}\n\nfunction ListboxItem({\n children,\n selected = false,\n disabled = false,\n onClick,\n onMouseEnter,\n className,\n style,\n ...htmlProps\n}: ListboxItemProps) {\n const context = React.useContext(ListboxContext);\n const generatedId = React.useId();\n const itemId = (htmlProps.id as string | undefined) ?? `listbox-item-${generatedId}`;\n const classes = [\n styles.item,\n selected && styles.itemSelected,\n disabled && styles.itemDisabled,\n context?.activeId === itemId && styles.itemActive,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!disabled) {\n context?.setActiveId(itemId);\n }\n onMouseEnter?.(event);\n };\n\n return (\n <div\n {...htmlProps}\n id={itemId}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled}\n data-active={context?.activeId === itemId || undefined}\n onClick={disabled ? undefined : onClick}\n onKeyDown={disabled ? undefined : (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick?.(); } }}\n onMouseEnter={handleMouseEnter}\n className={classes}\n style={style}\n >\n {children}\n </div>\n );\n}\n\nfunction ListboxGroup({ children, label, className, ...htmlProps }: ListboxGroupProps) {\n const classes = [styles.group, className].filter(Boolean).join(' ');\n const labelId = React.useId();\n\n return (\n <div\n {...htmlProps}\n role=\"group\"\n aria-labelledby={label ? labelId : undefined}\n className={classes}\n >\n {label && <div id={labelId} className={styles.groupLabel}>{label}</div>}\n {children}\n </div>\n );\n}\n\nfunction ListboxEmpty({ children, className, ...htmlProps }: ListboxEmptyProps) {\n const classes = [styles.empty, className].filter(Boolean).join(' ');\n return (\n <div\n {...htmlProps}\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n className={classes}\n >\n {children}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Listbox = Object.assign(ListboxRoot, {\n Item: ListboxItem,\n Group: ListboxGroup,\n Empty: ListboxEmpty,\n});\n\n// Re-export individual components\nexport { ListboxRoot, ListboxItem, ListboxGroup, ListboxEmpty };\n"],"names":["React","styles","jsx","jsxs"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Listbox/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACxE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC7F,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAaD,iBAAS,WAAW,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,SAAS,EACb,EAAE,YAAY,2CAuJd;AAED,iBAAS,WAAW,CAAC,EACnB,QAAQ,EACR,QAAgB,EAChB,QAAgB,EAChB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Listbox/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACxE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC7F,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAaD,iBAAS,WAAW,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,SAAS,EACb,EAAE,YAAY,2CAuJd;AAED,iBAAS,WAAW,CAAC,EACnB,QAAQ,EACR,QAAgB,EAChB,QAAgB,EAChB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,gBAAgB,2CAsClB;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,EAAE,iBAAiB,2CAepF;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,EAAE,iBAAiB,2CAa7E;AAMD,eAAO,MAAM,OAAO;;;;CAIlB,CAAC;AAGH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -167,6 +167,12 @@ function ListboxItem({
|
|
|
167
167
|
"aria-disabled": disabled,
|
|
168
168
|
"data-active": (context == null ? void 0 : context.activeId) === itemId || void 0,
|
|
169
169
|
onClick: disabled ? void 0 : onClick,
|
|
170
|
+
onKeyDown: disabled ? void 0 : (e) => {
|
|
171
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
172
|
+
e.preventDefault();
|
|
173
|
+
onClick == null ? void 0 : onClick();
|
|
174
|
+
}
|
|
175
|
+
},
|
|
170
176
|
onMouseEnter: handleMouseEnter,
|
|
171
177
|
className: classes,
|
|
172
178
|
style,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/Listbox/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Listbox.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ListboxProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport interface ListboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClick'> {\n children: React.ReactNode;\n /** Whether this item is currently selected/highlighted */\n selected?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport interface ListboxGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Group label */\n label?: string;\n}\n\nexport interface ListboxEmptyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\ninterface ListboxContextValue {\n activeId: string | null;\n setActiveId: (id: string | null) => void;\n}\n\nconst ListboxContext = React.createContext<ListboxContextValue | null>(null);\n\n// ============================================\n// Components\n// ============================================\n\nfunction ListboxRoot({\n children,\n className,\n style,\n 'aria-label': ariaLabel,\n tabIndex,\n onKeyDown,\n onFocus,\n ...htmlProps\n}: ListboxProps) {\n const classes = [styles.listbox, className].filter(Boolean).join(' ');\n const listboxRef = React.useRef<HTMLDivElement>(null);\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const getEnabledOptions = React.useCallback(() => {\n const listbox = listboxRef.current;\n if (!listbox) return [] as HTMLDivElement[];\n\n return Array.from(\n listbox.querySelectorAll<HTMLDivElement>('[role=\"option\"]')\n ).filter((option) => option.getAttribute('aria-disabled') !== 'true');\n }, []);\n\n const moveActive = React.useCallback(\n (direction: 'next' | 'prev' | 'first' | 'last') => {\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n if (direction === 'first') {\n setActiveId(options[0].id);\n return;\n }\n\n if (direction === 'last') {\n setActiveId(options[options.length - 1].id);\n return;\n }\n\n const currentIndex = activeId\n ? options.findIndex((option) => option.id === activeId)\n : -1;\n\n if (direction === 'next') {\n const nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % options.length;\n setActiveId(options[nextIndex].id);\n } else {\n const prevIndex = currentIndex < 0\n ? options.length - 1\n : (currentIndex - 1 + options.length) % options.length;\n setActiveId(options[prevIndex].id);\n }\n },\n [activeId, getEnabledOptions]\n );\n\n React.useEffect(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (!activeOption) return;\n\n const frame = window.requestAnimationFrame(() => {\n activeOption.scrollIntoView({ block: 'nearest' });\n });\n\n return () => {\n window.cancelAnimationFrame(frame);\n };\n }, [activeId]);\n\n const selectActiveItem = React.useCallback(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (activeOption && activeOption.getAttribute('aria-disabled') !== 'true') {\n activeOption.click();\n }\n }, [activeId]);\n\n const setDefaultActiveIfNeeded = React.useCallback(() => {\n if (activeId) return;\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n const selectedOption = options.find((option) => option.getAttribute('aria-selected') === 'true');\n setActiveId((selectedOption ?? options[0]).id);\n }, [activeId, getEnabledOptions]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveActive('next');\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveActive('prev');\n break;\n case 'Home':\n event.preventDefault();\n moveActive('first');\n break;\n case 'End':\n event.preventDefault();\n moveActive('last');\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n selectActiveItem();\n break;\n default:\n break;\n }\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n setDefaultActiveIfNeeded();\n onFocus?.(event);\n };\n\n const contextValue = React.useMemo<ListboxContextValue>(\n () => ({\n activeId,\n setActiveId,\n }),\n [activeId]\n );\n\n return (\n <ListboxContext.Provider value={contextValue}>\n <div\n ref={listboxRef}\n {...htmlProps}\n role=\"listbox\"\n aria-label={ariaLabel}\n aria-activedescendant={activeId ?? undefined}\n tabIndex={tabIndex ?? 0}\n className={classes}\n style={style}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n >\n {children}\n </div>\n </ListboxContext.Provider>\n );\n}\n\nfunction ListboxItem({\n children,\n selected = false,\n disabled = false,\n onClick,\n onMouseEnter,\n className,\n style,\n ...htmlProps\n}: ListboxItemProps) {\n const context = React.useContext(ListboxContext);\n const generatedId = React.useId();\n const itemId = (htmlProps.id as string | undefined) ?? `listbox-item-${generatedId}`;\n const classes = [\n styles.item,\n selected && styles.itemSelected,\n disabled && styles.itemDisabled,\n context?.activeId === itemId && styles.itemActive,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!disabled) {\n context?.setActiveId(itemId);\n }\n onMouseEnter?.(event);\n };\n\n return (\n <div\n {...htmlProps}\n id={itemId}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled}\n data-active={context?.activeId === itemId || undefined}\n onClick={disabled ? undefined : onClick}\n onMouseEnter={handleMouseEnter}\n className={classes}\n style={style}\n >\n {children}\n </div>\n );\n}\n\nfunction ListboxGroup({ children, label, className, ...htmlProps }: ListboxGroupProps) {\n const classes = [styles.group, className].filter(Boolean).join(' ');\n const labelId = React.useId();\n\n return (\n <div\n {...htmlProps}\n role=\"group\"\n aria-labelledby={label ? labelId : undefined}\n className={classes}\n >\n {label && <div id={labelId} className={styles.groupLabel}>{label}</div>}\n {children}\n </div>\n );\n}\n\nfunction ListboxEmpty({ children, className, ...htmlProps }: ListboxEmptyProps) {\n const classes = [styles.empty, className].filter(Boolean).join(' ');\n return (\n <div\n {...htmlProps}\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n className={classes}\n >\n {children}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Listbox = Object.assign(ListboxRoot, {\n Item: ListboxItem,\n Group: ListboxGroup,\n Empty: ListboxEmpty,\n});\n\n// Re-export individual components\nexport { ListboxRoot, ListboxItem, ListboxGroup, ListboxEmpty };\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/Listbox/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Listbox.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface ListboxProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport interface ListboxItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onClick'> {\n children: React.ReactNode;\n /** Whether this item is currently selected/highlighted */\n selected?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Click handler */\n onClick?: () => void;\n}\n\nexport interface ListboxGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Group label */\n label?: string;\n}\n\nexport interface ListboxEmptyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\ninterface ListboxContextValue {\n activeId: string | null;\n setActiveId: (id: string | null) => void;\n}\n\nconst ListboxContext = React.createContext<ListboxContextValue | null>(null);\n\n// ============================================\n// Components\n// ============================================\n\nfunction ListboxRoot({\n children,\n className,\n style,\n 'aria-label': ariaLabel,\n tabIndex,\n onKeyDown,\n onFocus,\n ...htmlProps\n}: ListboxProps) {\n const classes = [styles.listbox, className].filter(Boolean).join(' ');\n const listboxRef = React.useRef<HTMLDivElement>(null);\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const getEnabledOptions = React.useCallback(() => {\n const listbox = listboxRef.current;\n if (!listbox) return [] as HTMLDivElement[];\n\n return Array.from(\n listbox.querySelectorAll<HTMLDivElement>('[role=\"option\"]')\n ).filter((option) => option.getAttribute('aria-disabled') !== 'true');\n }, []);\n\n const moveActive = React.useCallback(\n (direction: 'next' | 'prev' | 'first' | 'last') => {\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n if (direction === 'first') {\n setActiveId(options[0].id);\n return;\n }\n\n if (direction === 'last') {\n setActiveId(options[options.length - 1].id);\n return;\n }\n\n const currentIndex = activeId\n ? options.findIndex((option) => option.id === activeId)\n : -1;\n\n if (direction === 'next') {\n const nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % options.length;\n setActiveId(options[nextIndex].id);\n } else {\n const prevIndex = currentIndex < 0\n ? options.length - 1\n : (currentIndex - 1 + options.length) % options.length;\n setActiveId(options[prevIndex].id);\n }\n },\n [activeId, getEnabledOptions]\n );\n\n React.useEffect(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (!activeOption) return;\n\n const frame = window.requestAnimationFrame(() => {\n activeOption.scrollIntoView({ block: 'nearest' });\n });\n\n return () => {\n window.cancelAnimationFrame(frame);\n };\n }, [activeId]);\n\n const selectActiveItem = React.useCallback(() => {\n if (!activeId) return;\n const listbox = listboxRef.current;\n if (!listbox) return;\n\n const escapedId = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(activeId)\n : activeId.replace(/[\"\\\\]/g, '\\\\$&');\n const activeOption = listbox.querySelector<HTMLElement>(`#${escapedId}`);\n if (activeOption && activeOption.getAttribute('aria-disabled') !== 'true') {\n activeOption.click();\n }\n }, [activeId]);\n\n const setDefaultActiveIfNeeded = React.useCallback(() => {\n if (activeId) return;\n const options = getEnabledOptions();\n if (options.length === 0) return;\n\n const selectedOption = options.find((option) => option.getAttribute('aria-selected') === 'true');\n setActiveId((selectedOption ?? options[0]).id);\n }, [activeId, getEnabledOptions]);\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveActive('next');\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveActive('prev');\n break;\n case 'Home':\n event.preventDefault();\n moveActive('first');\n break;\n case 'End':\n event.preventDefault();\n moveActive('last');\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n selectActiveItem();\n break;\n default:\n break;\n }\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n setDefaultActiveIfNeeded();\n onFocus?.(event);\n };\n\n const contextValue = React.useMemo<ListboxContextValue>(\n () => ({\n activeId,\n setActiveId,\n }),\n [activeId]\n );\n\n return (\n <ListboxContext.Provider value={contextValue}>\n <div\n ref={listboxRef}\n {...htmlProps}\n role=\"listbox\"\n aria-label={ariaLabel}\n aria-activedescendant={activeId ?? undefined}\n tabIndex={tabIndex ?? 0}\n className={classes}\n style={style}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n >\n {children}\n </div>\n </ListboxContext.Provider>\n );\n}\n\nfunction ListboxItem({\n children,\n selected = false,\n disabled = false,\n onClick,\n onMouseEnter,\n className,\n style,\n ...htmlProps\n}: ListboxItemProps) {\n const context = React.useContext(ListboxContext);\n const generatedId = React.useId();\n const itemId = (htmlProps.id as string | undefined) ?? `listbox-item-${generatedId}`;\n const classes = [\n styles.item,\n selected && styles.itemSelected,\n disabled && styles.itemDisabled,\n context?.activeId === itemId && styles.itemActive,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const handleMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!disabled) {\n context?.setActiveId(itemId);\n }\n onMouseEnter?.(event);\n };\n\n return (\n <div\n {...htmlProps}\n id={itemId}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled}\n data-active={context?.activeId === itemId || undefined}\n onClick={disabled ? undefined : onClick}\n onKeyDown={disabled ? undefined : (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick?.(); } }}\n onMouseEnter={handleMouseEnter}\n className={classes}\n style={style}\n >\n {children}\n </div>\n );\n}\n\nfunction ListboxGroup({ children, label, className, ...htmlProps }: ListboxGroupProps) {\n const classes = [styles.group, className].filter(Boolean).join(' ');\n const labelId = React.useId();\n\n return (\n <div\n {...htmlProps}\n role=\"group\"\n aria-labelledby={label ? labelId : undefined}\n className={classes}\n >\n {label && <div id={labelId} className={styles.groupLabel}>{label}</div>}\n {children}\n </div>\n );\n}\n\nfunction ListboxEmpty({ children, className, ...htmlProps }: ListboxEmptyProps) {\n const classes = [styles.empty, className].filter(Boolean).join(' ');\n return (\n <div\n {...htmlProps}\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n className={classes}\n >\n {children}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Listbox = Object.assign(ListboxRoot, {\n Item: ListboxItem,\n Group: ListboxGroup,\n Empty: ListboxEmpty,\n});\n\n// Re-export individual components\nexport { ListboxRoot, ListboxItem, ListboxGroup, ListboxEmpty };\n"],"names":[],"mappings":"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"}
|
|
@@ -72,17 +72,7 @@ const LoadingRoot = React__namespace.forwardRef(
|
|
|
72
72
|
overlay && Loading_module.default.overlay,
|
|
73
73
|
className
|
|
74
74
|
].filter(Boolean).join(" ");
|
|
75
|
-
const
|
|
76
|
-
switch (variant) {
|
|
77
|
-
case "dots":
|
|
78
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DotsAnimation, { className: Loading_module.default.dots });
|
|
79
|
-
case "pulse":
|
|
80
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PulseAnimation, { className: Loading_module.default.pulse });
|
|
81
|
-
case "spinner":
|
|
82
|
-
default:
|
|
83
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: Loading_module.default.spinnerIcon });
|
|
84
|
-
}
|
|
85
|
-
};
|
|
75
|
+
const animation = variant === "dots" ? /* @__PURE__ */ jsxRuntime.jsx(DotsAnimation, { className: Loading_module.default.dots }) : variant === "pulse" ? /* @__PURE__ */ jsxRuntime.jsx(PulseAnimation, { className: Loading_module.default.pulse }) : /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: Loading_module.default.spinnerIcon });
|
|
86
76
|
const content = /* @__PURE__ */ jsxRuntime.jsx(
|
|
87
77
|
"div",
|
|
88
78
|
{
|
|
@@ -92,7 +82,7 @@ const LoadingRoot = React__namespace.forwardRef(
|
|
|
92
82
|
"aria-label": label,
|
|
93
83
|
"aria-live": "polite",
|
|
94
84
|
...htmlProps,
|
|
95
|
-
children:
|
|
85
|
+
children: animation
|
|
96
86
|
}
|
|
97
87
|
);
|
|
98
88
|
if (overlay) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/Loading/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Loading.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type LoadingVariant = 'spinner' | 'dots' | 'pulse';\n\nexport interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Size of the loading indicator */\n size?: LoadingSize;\n /** Visual style of the loading indicator */\n variant?: LoadingVariant;\n /** Accessible label for screen readers */\n label?: string;\n /** Whether to center the loading indicator in its container */\n centered?: boolean;\n /** Whether to fill the parent container */\n fill?: boolean;\n /** Whether to show the loading indicator with a backdrop overlay */\n overlay?: boolean;\n /** Color variant - uses accent color by default, 'current' inherits text color */\n color?: 'accent' | 'current' | 'muted';\n}\n\nexport interface LoadingInlineProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Size of the loading indicator */\n size?: 'sm' | 'md';\n /** Accessible label */\n label?: string;\n}\n\nexport interface LoadingScreenProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Loading indicator size */\n size?: LoadingSize;\n /** Loading indicator variant */\n variant?: LoadingVariant;\n /** Optional label text to display */\n label?: string;\n /** Whether to show the label text visually */\n showLabel?: boolean;\n}\n\n// ============================================\n// Icons/Animations\n// ============================================\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nfunction DotsAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.dot} />\n <span className={styles.dot} />\n <span className={styles.dot} />\n </span>\n );\n}\n\nfunction PulseAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.pulseRing} />\n <span className={styles.pulseDot} />\n </span>\n );\n}\n\n// ============================================\n// Components\n// ============================================\n\nconst LoadingRoot = React.forwardRef<HTMLDivElement, LoadingProps>(\n function LoadingRoot(\n {\n size = 'md',\n variant = 'spinner',\n label = 'Loading...',\n centered = false,\n fill = false,\n overlay = false,\n color = 'accent',\n className,\n ...htmlProps\n },\n ref\n ) {\n const classes = [\n styles.loading,\n styles[size],\n styles[variant],\n styles[`color-${color}`],\n centered && styles.centered,\n fill && styles.fill,\n overlay && styles.overlay,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/Loading/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Loading.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type LoadingVariant = 'spinner' | 'dots' | 'pulse';\n\nexport interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Size of the loading indicator */\n size?: LoadingSize;\n /** Visual style of the loading indicator */\n variant?: LoadingVariant;\n /** Accessible label for screen readers */\n label?: string;\n /** Whether to center the loading indicator in its container */\n centered?: boolean;\n /** Whether to fill the parent container */\n fill?: boolean;\n /** Whether to show the loading indicator with a backdrop overlay */\n overlay?: boolean;\n /** Color variant - uses accent color by default, 'current' inherits text color */\n color?: 'accent' | 'current' | 'muted';\n}\n\nexport interface LoadingInlineProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Size of the loading indicator */\n size?: 'sm' | 'md';\n /** Accessible label */\n label?: string;\n}\n\nexport interface LoadingScreenProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Loading indicator size */\n size?: LoadingSize;\n /** Loading indicator variant */\n variant?: LoadingVariant;\n /** Optional label text to display */\n label?: string;\n /** Whether to show the label text visually */\n showLabel?: boolean;\n}\n\n// ============================================\n// Icons/Animations\n// ============================================\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nfunction DotsAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.dot} />\n <span className={styles.dot} />\n <span className={styles.dot} />\n </span>\n );\n}\n\nfunction PulseAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.pulseRing} />\n <span className={styles.pulseDot} />\n </span>\n );\n}\n\n// ============================================\n// Components\n// ============================================\n\nconst LoadingRoot = React.forwardRef<HTMLDivElement, LoadingProps>(\n function LoadingRoot(\n {\n size = 'md',\n variant = 'spinner',\n label = 'Loading...',\n centered = false,\n fill = false,\n overlay = false,\n color = 'accent',\n className,\n ...htmlProps\n },\n ref\n ) {\n const classes = [\n styles.loading,\n styles[size],\n styles[variant],\n styles[`color-${color}`],\n centered && styles.centered,\n fill && styles.fill,\n overlay && styles.overlay,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const animation = variant === 'dots'\n ? <DotsAnimation className={styles.dots} />\n : variant === 'pulse'\n ? <PulseAnimation className={styles.pulse} />\n : <SpinnerIcon className={styles.spinnerIcon} />;\n\n const content = (\n <div\n ref={ref}\n className={classes}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n {...htmlProps}\n >\n {animation}\n </div>\n );\n\n if (overlay) {\n return (\n <div className={styles.overlayBackdrop}>\n {content}\n </div>\n );\n }\n\n return content;\n }\n);\n\n// ============================================\n// Loading.Inline - Inline text loading indicator\n// ============================================\n\nfunction LoadingInline({\n size = 'sm',\n label = 'Loading...',\n className,\n ...htmlProps\n}: LoadingInlineProps) {\n const classes = [\n styles.inline,\n styles[`inline-${size}`],\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <span\n className={classes}\n role=\"status\"\n aria-label={label}\n {...htmlProps}\n >\n <SpinnerIcon className={styles.inlineSpinner} />\n </span>\n );\n}\n\n// ============================================\n// Loading.Screen - Full-screen loading state\n// ============================================\n\nfunction LoadingScreen({\n size = 'lg',\n variant = 'spinner',\n label = 'Loading...',\n showLabel = false,\n className,\n ...htmlProps\n}: LoadingScreenProps) {\n const classes = [\n styles.screen,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n className={classes}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n {...htmlProps}\n >\n <LoadingRoot size={size} variant={variant} label={label} />\n {showLabel && <span className={styles.screenLabel}>{label}</span>}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Loading = Object.assign(LoadingRoot, {\n Inline: LoadingInline,\n Screen: LoadingScreen,\n});\n\n// Re-export individual components for tree-shaking\nexport {\n LoadingRoot,\n LoadingInline,\n LoadingScreen,\n};\n"],"names":["jsx","jsxs","styles","React","LoadingRoot"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Loading/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACxE,oCAAoC;IACpC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC/E,oCAAoC;IACpC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,6BAA6B;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA+CD,QAAA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Loading/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACxE,oCAAoC;IACpC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC/E,oCAAoC;IACpC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,6BAA6B;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA+CD,QAAA,MAAM,WAAW,qFAyDhB,CAAC;AAMF,iBAAS,aAAa,CAAC,EACrB,IAAW,EACX,KAAoB,EACpB,SAAS,EACT,GAAG,SAAS,EACb,EAAE,kBAAkB,2CAmBpB;AAMD,iBAAS,aAAa,CAAC,EACrB,IAAW,EACX,OAAmB,EACnB,KAAoB,EACpB,SAAiB,EACjB,SAAS,EACT,GAAG,SAAS,EACb,EAAE,kBAAkB,2CAoBpB;AAMD,eAAO,MAAM,OAAO;;;CAGlB,CAAC;AAGH,OAAO,EACL,WAAW,EACX,aAAa,EACb,aAAa,GACd,CAAC"}
|
|
@@ -53,17 +53,7 @@ const LoadingRoot = React.forwardRef(
|
|
|
53
53
|
overlay && styles.overlay,
|
|
54
54
|
className
|
|
55
55
|
].filter(Boolean).join(" ");
|
|
56
|
-
const
|
|
57
|
-
switch (variant) {
|
|
58
|
-
case "dots":
|
|
59
|
-
return /* @__PURE__ */ jsx(DotsAnimation, { className: styles.dots });
|
|
60
|
-
case "pulse":
|
|
61
|
-
return /* @__PURE__ */ jsx(PulseAnimation, { className: styles.pulse });
|
|
62
|
-
case "spinner":
|
|
63
|
-
default:
|
|
64
|
-
return /* @__PURE__ */ jsx(SpinnerIcon, { className: styles.spinnerIcon });
|
|
65
|
-
}
|
|
66
|
-
};
|
|
56
|
+
const animation = variant === "dots" ? /* @__PURE__ */ jsx(DotsAnimation, { className: styles.dots }) : variant === "pulse" ? /* @__PURE__ */ jsx(PulseAnimation, { className: styles.pulse }) : /* @__PURE__ */ jsx(SpinnerIcon, { className: styles.spinnerIcon });
|
|
67
57
|
const content = /* @__PURE__ */ jsx(
|
|
68
58
|
"div",
|
|
69
59
|
{
|
|
@@ -73,7 +63,7 @@ const LoadingRoot = React.forwardRef(
|
|
|
73
63
|
"aria-label": label,
|
|
74
64
|
"aria-live": "polite",
|
|
75
65
|
...htmlProps,
|
|
76
|
-
children:
|
|
66
|
+
children: animation
|
|
77
67
|
}
|
|
78
68
|
);
|
|
79
69
|
if (overlay) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/Loading/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Loading.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type LoadingVariant = 'spinner' | 'dots' | 'pulse';\n\nexport interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Size of the loading indicator */\n size?: LoadingSize;\n /** Visual style of the loading indicator */\n variant?: LoadingVariant;\n /** Accessible label for screen readers */\n label?: string;\n /** Whether to center the loading indicator in its container */\n centered?: boolean;\n /** Whether to fill the parent container */\n fill?: boolean;\n /** Whether to show the loading indicator with a backdrop overlay */\n overlay?: boolean;\n /** Color variant - uses accent color by default, 'current' inherits text color */\n color?: 'accent' | 'current' | 'muted';\n}\n\nexport interface LoadingInlineProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Size of the loading indicator */\n size?: 'sm' | 'md';\n /** Accessible label */\n label?: string;\n}\n\nexport interface LoadingScreenProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Loading indicator size */\n size?: LoadingSize;\n /** Loading indicator variant */\n variant?: LoadingVariant;\n /** Optional label text to display */\n label?: string;\n /** Whether to show the label text visually */\n showLabel?: boolean;\n}\n\n// ============================================\n// Icons/Animations\n// ============================================\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nfunction DotsAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.dot} />\n <span className={styles.dot} />\n <span className={styles.dot} />\n </span>\n );\n}\n\nfunction PulseAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.pulseRing} />\n <span className={styles.pulseDot} />\n </span>\n );\n}\n\n// ============================================\n// Components\n// ============================================\n\nconst LoadingRoot = React.forwardRef<HTMLDivElement, LoadingProps>(\n function LoadingRoot(\n {\n size = 'md',\n variant = 'spinner',\n label = 'Loading...',\n centered = false,\n fill = false,\n overlay = false,\n color = 'accent',\n className,\n ...htmlProps\n },\n ref\n ) {\n const classes = [\n styles.loading,\n styles[size],\n styles[variant],\n styles[`color-${color}`],\n centered && styles.centered,\n fill && styles.fill,\n overlay && styles.overlay,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/Loading/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport styles from './Loading.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type LoadingSize = 'sm' | 'md' | 'lg' | 'xl';\nexport type LoadingVariant = 'spinner' | 'dots' | 'pulse';\n\nexport interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Size of the loading indicator */\n size?: LoadingSize;\n /** Visual style of the loading indicator */\n variant?: LoadingVariant;\n /** Accessible label for screen readers */\n label?: string;\n /** Whether to center the loading indicator in its container */\n centered?: boolean;\n /** Whether to fill the parent container */\n fill?: boolean;\n /** Whether to show the loading indicator with a backdrop overlay */\n overlay?: boolean;\n /** Color variant - uses accent color by default, 'current' inherits text color */\n color?: 'accent' | 'current' | 'muted';\n}\n\nexport interface LoadingInlineProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Size of the loading indicator */\n size?: 'sm' | 'md';\n /** Accessible label */\n label?: string;\n}\n\nexport interface LoadingScreenProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Loading indicator size */\n size?: LoadingSize;\n /** Loading indicator variant */\n variant?: LoadingVariant;\n /** Optional label text to display */\n label?: string;\n /** Whether to show the label text visually */\n showLabel?: boolean;\n}\n\n// ============================================\n// Icons/Animations\n// ============================================\n\nfunction SpinnerIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\nfunction DotsAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.dot} />\n <span className={styles.dot} />\n <span className={styles.dot} />\n </span>\n );\n}\n\nfunction PulseAnimation({ className }: { className?: string }) {\n return (\n <span className={className} aria-hidden=\"true\">\n <span className={styles.pulseRing} />\n <span className={styles.pulseDot} />\n </span>\n );\n}\n\n// ============================================\n// Components\n// ============================================\n\nconst LoadingRoot = React.forwardRef<HTMLDivElement, LoadingProps>(\n function LoadingRoot(\n {\n size = 'md',\n variant = 'spinner',\n label = 'Loading...',\n centered = false,\n fill = false,\n overlay = false,\n color = 'accent',\n className,\n ...htmlProps\n },\n ref\n ) {\n const classes = [\n styles.loading,\n styles[size],\n styles[variant],\n styles[`color-${color}`],\n centered && styles.centered,\n fill && styles.fill,\n overlay && styles.overlay,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const animation = variant === 'dots'\n ? <DotsAnimation className={styles.dots} />\n : variant === 'pulse'\n ? <PulseAnimation className={styles.pulse} />\n : <SpinnerIcon className={styles.spinnerIcon} />;\n\n const content = (\n <div\n ref={ref}\n className={classes}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n {...htmlProps}\n >\n {animation}\n </div>\n );\n\n if (overlay) {\n return (\n <div className={styles.overlayBackdrop}>\n {content}\n </div>\n );\n }\n\n return content;\n }\n);\n\n// ============================================\n// Loading.Inline - Inline text loading indicator\n// ============================================\n\nfunction LoadingInline({\n size = 'sm',\n label = 'Loading...',\n className,\n ...htmlProps\n}: LoadingInlineProps) {\n const classes = [\n styles.inline,\n styles[`inline-${size}`],\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <span\n className={classes}\n role=\"status\"\n aria-label={label}\n {...htmlProps}\n >\n <SpinnerIcon className={styles.inlineSpinner} />\n </span>\n );\n}\n\n// ============================================\n// Loading.Screen - Full-screen loading state\n// ============================================\n\nfunction LoadingScreen({\n size = 'lg',\n variant = 'spinner',\n label = 'Loading...',\n showLabel = false,\n className,\n ...htmlProps\n}: LoadingScreenProps) {\n const classes = [\n styles.screen,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n className={classes}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n {...htmlProps}\n >\n <LoadingRoot size={size} variant={variant} label={label} />\n {showLabel && <span className={styles.screenLabel}>{label}</span>}\n </div>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Loading = Object.assign(LoadingRoot, {\n Inline: LoadingInline,\n Screen: LoadingScreen,\n});\n\n// Re-export individual components for tree-shaking\nexport {\n LoadingRoot,\n LoadingInline,\n LoadingScreen,\n};\n"],"names":["LoadingRoot"],"mappings":"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"}
|
|
@@ -571,7 +571,18 @@ function MobileCollapsibleSection({
|
|
|
571
571
|
}) {
|
|
572
572
|
return /* @__PURE__ */ jsxRuntime.jsxs(index$1.Collapsible, { defaultOpen: false, children: [
|
|
573
573
|
/* @__PURE__ */ jsxRuntime.jsx(index$1.Collapsible.Trigger, { className: NavigationMenu_module.default.drawerCollapsibleTrigger, children: label }),
|
|
574
|
-
/* @__PURE__ */ jsxRuntime.jsx(index$1.Collapsible.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
574
|
+
/* @__PURE__ */ jsxRuntime.jsx(index$1.Collapsible.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
575
|
+
"div",
|
|
576
|
+
{
|
|
577
|
+
className: NavigationMenu_module.default.drawerCollapsibleContent,
|
|
578
|
+
onClick: onLinkClick,
|
|
579
|
+
onKeyDown: (e) => {
|
|
580
|
+
if (e.key === "Enter") onLinkClick();
|
|
581
|
+
},
|
|
582
|
+
role: "group",
|
|
583
|
+
children
|
|
584
|
+
}
|
|
585
|
+
) })
|
|
575
586
|
] });
|
|
576
587
|
}
|
|
577
588
|
const NavigationMenu = Object.assign(NavigationMenuRoot, {
|