@seedgrid/fe-components 2026.3.31 → 2026.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
+ import { createPortal } from "react-dom";
5
+ import { Check, GripVertical, SlidersHorizontal } from "lucide-react";
4
6
  import { SgButton } from "../buttons/SgButton";
5
7
  import { SgGroupBox } from "../layout/SgGroupBox";
6
8
  import { t, useComponentsI18n } from "../i18n";
@@ -112,6 +114,28 @@ function rowsAreEqual(rowA, rowB, dataKey) {
112
114
  return rowA === rowB;
113
115
  return getRowIdentity(rowA, dataKey) === getRowIdentity(rowB, dataKey);
114
116
  }
117
+ function getColumnKey(column, index) {
118
+ if (column.columnId?.trim())
119
+ return `columnId:${column.columnId.trim()}`;
120
+ if (column.field?.trim())
121
+ return `field:${column.field.trim()}`;
122
+ return `index:${index}`;
123
+ }
124
+ function moveItem(list, fromIndex, toIndex) {
125
+ if (fromIndex === toIndex)
126
+ return list;
127
+ if (fromIndex < 0 || fromIndex >= list.length)
128
+ return list;
129
+ if (toIndex < 0 || toIndex >= list.length)
130
+ return list;
131
+ const next = [...list];
132
+ const item = next[fromIndex];
133
+ if (item === undefined)
134
+ return list;
135
+ next.splice(fromIndex, 1);
136
+ next.splice(toIndex, 0, item);
137
+ return next;
138
+ }
115
139
  function resolveAlignmentClass(align) {
116
140
  if (align === "center")
117
141
  return "text-center";
@@ -121,7 +145,7 @@ function resolveAlignmentClass(align) {
121
145
  }
122
146
  function SgDatatableBase(props, imperativeRef) {
123
147
  const i18n = useComponentsI18n();
124
- const { id, title, value, columns, dataKey, lazy = false, totalRecords: controlledTotalRecords, paginator = false, rows = 10, first, rowsPerPageOptions, onPage, sortField, sortOrder, onSort, removableSort = true, selectionMode, selection, onSelectionChange, showGlobalFilter = false, globalFilter, globalFilterPlaceholder, onGlobalFilterChange, showColumnFilters = false, filters, onFilter, showClearFiltersButton = false, stripedRows = false, showGridlines = false, hoverableRows = true, loading = false, emptyMessage, className = "", style, tableClassName = "", rowClassName, groupBoxProps = {} } = props;
148
+ const { id, title, value, columns, dataKey, lazy = false, totalRecords: controlledTotalRecords, paginator = false, rows = 10, first, rowsPerPageOptions, onPage, sortField, sortOrder, onSort, removableSort = true, selectionMode, selection, onSelectionChange, showGlobalFilter = false, globalFilter, globalFilterPlaceholder, onGlobalFilterChange, showColumnFilters = false, filters, onFilter, showClearFiltersButton = false, stripedRows = false, showGridlines = false, hoverableRows = true, loading = false, emptyMessage, className = "", style, tableClassName = "", rowClassName, groupBoxProps = {}, showColumnManager = true, columnManagerLabel, columnManagerMaxHeight = 320 } = props;
125
149
  const isFirstControlled = first !== undefined;
126
150
  const isSortFieldControlled = sortField !== undefined;
127
151
  const isSortOrderControlled = sortOrder !== undefined;
@@ -135,6 +159,22 @@ function SgDatatableBase(props, imperativeRef) {
135
159
  const [internalSelection, setInternalSelection] = React.useState(null);
136
160
  const [internalGlobalFilter, setInternalGlobalFilter] = React.useState(globalFilter ?? "");
137
161
  const [internalFilters, setInternalFilters] = React.useState(() => normalizeFilters(filters));
162
+ const columnManagerRef = React.useRef(null);
163
+ const columnManagerButtonRef = React.useRef(null);
164
+ const columnManagerPanelRef = React.useRef(null);
165
+ const [isColumnManagerOpen, setIsColumnManagerOpen] = React.useState(false);
166
+ const [draggingColumnKey, setDraggingColumnKey] = React.useState(null);
167
+ const [columnManagerPosition, setColumnManagerPosition] = React.useState(null);
168
+ const columnDescriptors = React.useMemo(() => columns.map((column, index) => ({
169
+ key: getColumnKey(column, index),
170
+ column,
171
+ originalIndex: index
172
+ })), [columns]);
173
+ const [columnOrder, setColumnOrder] = React.useState(() => columnDescriptors.map((item) => item.key));
174
+ const [hiddenColumnsMap, setHiddenColumnsMap] = React.useState(() => columnDescriptors.reduce((acc, item) => {
175
+ acc[item.key] = Boolean(item.column.hidden);
176
+ return acc;
177
+ }, {}));
138
178
  React.useEffect(() => {
139
179
  if (!isFirstControlled)
140
180
  return;
@@ -168,7 +208,75 @@ function SgDatatableBase(props, imperativeRef) {
168
208
  return;
169
209
  setInternalFilters(normalizeFilters(filters));
170
210
  }, [isFiltersControlled, filters]);
171
- const visibleColumns = React.useMemo(() => columns.filter((column) => !column.hidden), [columns]);
211
+ React.useEffect(() => {
212
+ const availableKeys = columnDescriptors.map((item) => item.key);
213
+ setColumnOrder((prev) => {
214
+ const kept = prev.filter((key) => availableKeys.includes(key));
215
+ const missing = availableKeys.filter((key) => !kept.includes(key));
216
+ return [...kept, ...missing];
217
+ });
218
+ setHiddenColumnsMap((prev) => {
219
+ const next = {};
220
+ for (const item of columnDescriptors) {
221
+ next[item.key] = prev[item.key] ?? Boolean(item.column.hidden);
222
+ }
223
+ return next;
224
+ });
225
+ }, [columnDescriptors]);
226
+ React.useEffect(() => {
227
+ if (!isColumnManagerOpen)
228
+ return;
229
+ const handlePointerDown = (event) => {
230
+ const target = event.target;
231
+ if (columnManagerRef.current?.contains(target))
232
+ return;
233
+ if (columnManagerPanelRef.current?.contains(target))
234
+ return;
235
+ setIsColumnManagerOpen(false);
236
+ };
237
+ document.addEventListener("mousedown", handlePointerDown);
238
+ return () => document.removeEventListener("mousedown", handlePointerDown);
239
+ }, [isColumnManagerOpen]);
240
+ const updateColumnManagerPosition = React.useCallback(() => {
241
+ const button = columnManagerButtonRef.current;
242
+ if (!button)
243
+ return;
244
+ const rect = button.getBoundingClientRect();
245
+ const panelWidth = 300;
246
+ const viewportPadding = 12;
247
+ const left = Math.min(Math.max(rect.left, viewportPadding), Math.max(viewportPadding, window.innerWidth - panelWidth - viewportPadding));
248
+ setColumnManagerPosition({
249
+ top: rect.bottom + 8,
250
+ left
251
+ });
252
+ }, []);
253
+ React.useLayoutEffect(() => {
254
+ if (!isColumnManagerOpen)
255
+ return;
256
+ updateColumnManagerPosition();
257
+ const raf = window.requestAnimationFrame(updateColumnManagerPosition);
258
+ return () => window.cancelAnimationFrame(raf);
259
+ }, [isColumnManagerOpen, updateColumnManagerPosition]);
260
+ React.useEffect(() => {
261
+ if (!isColumnManagerOpen)
262
+ return;
263
+ const handleViewportChange = () => updateColumnManagerPosition();
264
+ const useCapture = true;
265
+ window.addEventListener("resize", handleViewportChange);
266
+ window.addEventListener("scroll", handleViewportChange, useCapture);
267
+ return () => {
268
+ window.removeEventListener("resize", handleViewportChange);
269
+ window.removeEventListener("scroll", handleViewportChange, useCapture);
270
+ };
271
+ }, [isColumnManagerOpen, updateColumnManagerPosition]);
272
+ const orderedColumns = React.useMemo(() => {
273
+ const map = new Map(columnDescriptors.map((item) => [item.key, item]));
274
+ return columnOrder
275
+ .map((key) => map.get(key))
276
+ .filter((item) => Boolean(item));
277
+ }, [columnDescriptors, columnOrder]);
278
+ const visibleColumns = React.useMemo(() => orderedColumns.filter((item) => !hiddenColumnsMap[item.key]).map((item) => item.column), [orderedColumns, hiddenColumnsMap]);
279
+ const visibleColumnCount = React.useMemo(() => orderedColumns.filter((item) => !hiddenColumnsMap[item.key]).length, [orderedColumns, hiddenColumnsMap]);
172
280
  const currentFirst = isFirstControlled ? Math.max(0, first ?? 0) : internalFirst;
173
281
  const currentRows = Math.max(1, internalRows);
174
282
  const currentSortField = isSortFieldControlled ? sortField ?? null : internalSortField;
@@ -379,61 +487,134 @@ function SgDatatableBase(props, imperativeRef) {
379
487
  : [...previous, rowData];
380
488
  commitSelection(next);
381
489
  }, [selectionMode, currentSelection, dataKey, commitSelection]);
490
+ const resolvedColumnManagerLabel = columnManagerLabel ??
491
+ resolveMessage(t(i18n, "components.datatable.columns"), "components.datatable.columns", "Colunas");
492
+ const restoreColumnsLabel = resolveMessage(t(i18n, "components.datatable.restoreColumns"), "components.datatable.restoreColumns", "Restaurar padrão");
493
+ const showAllColumnsLabel = resolveMessage(t(i18n, "components.datatable.showAllColumns"), "components.datatable.showAllColumns", "Mostrar todas");
494
+ const dragHandleLabel = resolveMessage(t(i18n, "components.datatable.dragToReorder"), "components.datatable.dragToReorder", "Arrastar para reordenar");
495
+ const toggleColumnVisibility = React.useCallback((columnKey, forceVisible) => {
496
+ setHiddenColumnsMap((prev) => {
497
+ const isCurrentlyHidden = Boolean(prev[columnKey]);
498
+ const willHide = forceVisible === undefined ? !isCurrentlyHidden : !forceVisible;
499
+ if (willHide && visibleColumnCount <= 1) {
500
+ return prev;
501
+ }
502
+ return {
503
+ ...prev,
504
+ [columnKey]: willHide
505
+ };
506
+ });
507
+ }, [visibleColumnCount]);
508
+ const handleReorderColumn = React.useCallback((fromKey, toKey) => {
509
+ setColumnOrder((prev) => {
510
+ const fromIndex = prev.indexOf(fromKey);
511
+ const toIndex = prev.indexOf(toKey);
512
+ if (fromIndex < 0 || toIndex < 0)
513
+ return prev;
514
+ return moveItem(prev, fromIndex, toIndex);
515
+ });
516
+ }, []);
517
+ const restoreDefaultColumns = React.useCallback(() => {
518
+ setColumnOrder(columnDescriptors.map((item) => item.key));
519
+ setHiddenColumnsMap(columnDescriptors.reduce((acc, item) => {
520
+ acc[item.key] = Boolean(item.column.hidden);
521
+ return acc;
522
+ }, {}));
523
+ }, [columnDescriptors]);
524
+ const showAllColumns = React.useCallback(() => {
525
+ setHiddenColumnsMap((prev) => {
526
+ const next = { ...prev };
527
+ for (const item of columnDescriptors) {
528
+ next[item.key] = false;
529
+ }
530
+ return next;
531
+ });
532
+ }, [columnDescriptors]);
382
533
  const resolvedTitle = (groupBoxProps.title ?? title ?? "").trim() || " ";
383
- return (_jsx("div", { className: className, style: style, children: _jsx(SgGroupBox, { ...groupBoxProps, title: resolvedTitle, children: _jsxs("div", { className: "space-y-3", children: [shouldShowToolbar ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [showGlobalFilter ? (_jsx("input", { value: currentGlobalFilter, onChange: (event) => commitFilters(currentFilters, event.target.value), placeholder: globalFilterLabel, className: "min-w-[220px] flex-1 rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-3 py-2 text-sm text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null, showClearFiltersButton ? (_jsx(SgButton, { size: "sm", appearance: "outline", onClick: clearFilters, children: clearFiltersLabel })) : null] })) : null, _jsx("div", { className: "relative", children: _jsx("div", { className: "overflow-x-auto rounded-lg border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))]", children: _jsxs("table", { id: id, className: cn("min-w-full border-collapse text-sm", tableClassName), children: [_jsxs("thead", { children: [_jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
384
- const sortCandidate = column.sortField ?? column.field;
385
- const isSorted = Boolean(sortCandidate) && sortCandidate === currentSortField;
386
- const sortIcon = !column.sortable
387
- ? null
388
- : isSorted
389
- ? currentSortOrder === 1
390
- ? " ^"
391
- : currentSortOrder === -1
392
- ? " v"
393
- : " <>"
394
- : " <>";
395
- return (_jsx("th", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.headerClassName, column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: column.sortable ? (_jsxs("button", { type: "button", onClick: () => handleHeaderSort(column), className: cn("inline-flex items-center gap-1 font-semibold", resolveAlignmentClass(column.align), "text-[rgb(var(--sg-text))] hover:text-[rgb(var(--sg-primary-600))]"), children: [_jsx("span", { children: column.header }), _jsx("span", { "aria-hidden": "true", children: sortIcon })] })) : (_jsx("span", { children: column.header })) }, `head-${column.field ?? columnIndex}`));
396
- }) }), shouldShowFiltersRow ? (_jsx("tr", { children: visibleColumns.map((column, columnIndex) => {
397
- const filterField = column.filterField ?? column.field;
398
- const filterValue = filterField ? currentFilters[filterField] ?? "" : "";
399
- return (_jsx("th", { className: cn("px-3 py-2 align-top", showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]"), children: column.filter && filterField ? (_jsx("input", { value: filterValue, onChange: (event) => {
400
- const nextFilters = {
401
- ...currentFilters,
402
- [filterField]: event.target.value
403
- };
404
- const normalized = normalizeFilters(nextFilters);
405
- commitFilters(normalized, currentGlobalFilter);
406
- }, placeholder: column.filterPlaceholder ?? t(i18n, "components.datatable.columnFilterPlaceholder", { column: String(column.header ?? "") }), className: "w-full rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null }, `filter-${column.field ?? columnIndex}`));
407
- }) })) : null] }), _jsx("tbody", { children: loading ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: loadingLabel }) })) : pagedRows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: emptyLabel }) })) : (pagedRows.map((rowData, rowIndex) => {
408
- const absoluteRowIndex = safeFirst + rowIndex;
409
- const selected = isRowSelected(rowData);
410
- const customRowClass = typeof rowClassName === "function" ? rowClassName(rowData, absoluteRowIndex) : rowClassName;
411
- return (_jsx("tr", { "aria-selected": selected || undefined, onClick: (event) => {
412
- const target = event.target;
413
- if (target.closest("button,a,input,select,textarea,label,[data-sg-stop-row-select='true']")) {
414
- return;
415
- }
416
- handleRowSelection(rowData);
417
- }, className: cn(selectionMode ? "cursor-pointer" : "", stripedRows && absoluteRowIndex % 2 === 1 ? "bg-[rgb(var(--sg-primary-50))]" : "", hoverableRows ? "hover:bg-[rgb(var(--sg-primary-100))]" : "", selected ? "bg-[rgb(var(--sg-primary-100))]" : "", customRowClass), children: visibleColumns.map((column, columnIndex) => {
418
- const cellField = column.field;
419
- const cellValue = getFieldValue(rowData, cellField);
420
- const customCellClass = typeof column.bodyClassName === "function"
421
- ? column.bodyClassName(rowData, absoluteRowIndex)
422
- : column.bodyClassName;
423
- const renderedValue = column.body
424
- ? column.body(rowData, {
425
- rowData,
426
- rowIndex: absoluteRowIndex,
427
- field: cellField,
428
- value: cellValue
429
- })
430
- : (_jsx("span", { children: cellValue === null || cellValue === undefined ? "-" : String(cellValue) }));
431
- return (_jsx("td", { className: cn("px-3 py-2 text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.className, customCellClass), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: renderedValue }, `cell-${cellField ?? columnIndex}-${absoluteRowIndex}`));
432
- }) }, String(getRowIdentity(rowData, dataKey) ?? absoluteRowIndex)));
433
- })) }), hasFooter ? (_jsx("tfoot", { children: _jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
434
- const footerValue = typeof column.footer === "function" ? column.footer(sortedRows) : column.footer;
435
- return (_jsx("td", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-t border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-t border-[rgb(var(--sg-border))]", column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: footerValue ?? null }, `foot-${column.field ?? columnIndex}`));
436
- }) }) })) : null] }) }) }), paginator ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage <= 1, onClick: () => goToPage(currentPage - 1), children: prevLabel }), pageWindow.map((pageNumber) => (_jsx(SgButton, { size: "sm", appearance: pageNumber === currentPage ? "solid" : "outline", onClick: () => goToPage(pageNumber), children: String(pageNumber) }, `page-${pageNumber}`))), _jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage >= pageCount, onClick: () => goToPage(currentPage + 1), children: nextLabel }), _jsx("span", { className: "min-w-[180px] text-xs text-[rgb(var(--sg-muted))] md:ml-auto", children: pageReport }), rowsPerPageOptions && rowsPerPageOptions.length > 0 ? (_jsxs("label", { className: "ml-auto inline-flex items-center gap-2 text-xs text-[rgb(var(--sg-muted))] md:ml-0", children: [_jsx("span", { children: rowsPerPageLabel }), _jsx("select", { value: currentRows, onChange: (event) => {
534
+ return (_jsx("div", { className: className, style: style, children: _jsx(SgGroupBox, { ...groupBoxProps, title: resolvedTitle, children: _jsxs("div", { className: "space-y-3", children: [shouldShowToolbar ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [showGlobalFilter ? (_jsx("input", { value: currentGlobalFilter, onChange: (event) => commitFilters(currentFilters, event.target.value), placeholder: globalFilterLabel, className: "min-w-[220px] flex-1 rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-3 py-2 text-sm text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null, showClearFiltersButton ? (_jsx(SgButton, { size: "sm", appearance: "outline", onClick: clearFilters, children: clearFiltersLabel })) : null] })) : null, _jsxs("div", { className: "relative", ref: columnManagerRef, children: [showColumnManager ? (_jsx("div", { className: "mb-2 flex items-center justify-start", children: _jsx("button", { ref: columnManagerButtonRef, type: "button", "aria-label": resolvedColumnManagerLabel, title: resolvedColumnManagerLabel, onClick: () => setIsColumnManagerOpen((prev) => !prev), className: "inline-flex h-9 w-9 items-center justify-center rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] text-[rgb(var(--sg-primary-600))] shadow-sm transition hover:bg-[rgb(var(--sg-primary-50))] hover:text-[rgb(var(--sg-primary-700))]", children: _jsx(SlidersHorizontal, { size: 18 }) }) })) : null, showColumnManager && isColumnManagerOpen && columnManagerPosition && typeof document !== "undefined"
535
+ ? createPortal(_jsxs("div", { ref: columnManagerPanelRef, className: "fixed z-[1400] w-[300px] rounded-xl border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] shadow-xl", style: {
536
+ top: columnManagerPosition.top,
537
+ left: columnManagerPosition.left
538
+ }, children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-[rgb(var(--sg-border))] px-4 py-3", children: [_jsx(SlidersHorizontal, { size: 18, className: "text-[rgb(var(--sg-primary-600))]" }), _jsx("span", { className: "text-sm font-semibold text-[rgb(var(--sg-text))]", children: resolvedColumnManagerLabel })] }), _jsx("div", { className: "overflow-y-auto px-2 py-2", style: { maxHeight: toCssSize(columnManagerMaxHeight) }, children: _jsx("div", { className: "space-y-1", children: orderedColumns.map((item) => {
539
+ const isHidden = Boolean(hiddenColumnsMap[item.key]);
540
+ const isHideable = item.column.hideable !== false;
541
+ const isReorderable = item.column.reorderable !== false;
542
+ const canHideThisColumn = isHideable && (!isHidden ? visibleColumnCount > 1 : true);
543
+ const columnLabel = typeof item.column.header === "string" || typeof item.column.header === "number"
544
+ ? String(item.column.header)
545
+ : item.column.field ?? item.key;
546
+ return (_jsxs("div", { draggable: isReorderable, onDragStart: () => setDraggingColumnKey(item.key), onDragOver: (event) => {
547
+ if (!isReorderable)
548
+ return;
549
+ event.preventDefault();
550
+ }, onDrop: (event) => {
551
+ event.preventDefault();
552
+ if (!isReorderable)
553
+ return;
554
+ if (!draggingColumnKey || draggingColumnKey === item.key)
555
+ return;
556
+ handleReorderColumn(draggingColumnKey, item.key);
557
+ setDraggingColumnKey(null);
558
+ }, onDragEnd: () => setDraggingColumnKey(null), className: cn("flex items-center gap-3 rounded-md px-2 py-2", draggingColumnKey === item.key ? "opacity-60" : "", "hover:bg-[rgb(var(--sg-primary-50))]"), children: [_jsx("button", { type: "button", disabled: !canHideThisColumn, onClick: () => toggleColumnVisibility(item.key), className: cn("inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md border transition", !isHidden
559
+ ? "border-[rgb(var(--sg-primary-600))] bg-[rgb(var(--sg-primary-600))] text-white"
560
+ : "border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))] text-transparent", !canHideThisColumn ? "cursor-not-allowed opacity-50" : "hover:scale-[1.02]"), children: _jsx(Check, { size: 14 }) }), _jsx("button", { type: "button", disabled: !canHideThisColumn, onClick: () => toggleColumnVisibility(item.key), className: cn("flex-1 truncate text-left text-sm", isHidden
561
+ ? "text-[rgb(var(--sg-muted))]"
562
+ : "text-[rgb(var(--sg-text))]", !canHideThisColumn ? "cursor-not-allowed" : ""), children: columnLabel }), _jsx("div", { className: cn("inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-[rgb(var(--sg-muted))]", isReorderable ? "cursor-grab active:cursor-grabbing" : "opacity-40"), title: dragHandleLabel, children: _jsx(GripVertical, { size: 16 }) })] }, `manager-${item.key}`));
563
+ }) }) }), _jsxs("div", { className: "flex items-center gap-2 border-t border-[rgb(var(--sg-border))] px-3 py-3", children: [_jsx(SgButton, { size: "sm", appearance: "outline", onClick: restoreDefaultColumns, children: restoreColumnsLabel }), _jsx(SgButton, { size: "sm", appearance: "outline", onClick: showAllColumns, children: showAllColumnsLabel })] })] }), document.body)
564
+ : null, _jsx("div", { className: "overflow-x-auto rounded-lg border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface))]", children: _jsxs("table", { id: id, className: cn("min-w-full border-collapse text-sm", tableClassName), children: [_jsxs("thead", { children: [_jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
565
+ const sortCandidate = column.sortField ?? column.field;
566
+ const isSorted = Boolean(sortCandidate) && sortCandidate === currentSortField;
567
+ const sortIcon = !column.sortable
568
+ ? null
569
+ : isSorted
570
+ ? currentSortOrder === 1
571
+ ? " ^"
572
+ : currentSortOrder === -1
573
+ ? " v"
574
+ : " <>"
575
+ : " <>";
576
+ return (_jsx("th", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.headerClassName, column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: column.sortable ? (_jsxs("button", { type: "button", onClick: () => handleHeaderSort(column), className: cn("inline-flex items-center gap-1 font-semibold", resolveAlignmentClass(column.align), "text-[rgb(var(--sg-text))] hover:text-[rgb(var(--sg-primary-600))]"), children: [_jsx("span", { children: column.header }), _jsx("span", { "aria-hidden": "true", children: sortIcon })] })) : (_jsx("span", { children: column.header })) }, `head-${column.columnId ?? column.field ?? columnIndex}`));
577
+ }) }), shouldShowFiltersRow ? (_jsx("tr", { children: visibleColumns.map((column, columnIndex) => {
578
+ const filterField = column.filterField ?? column.field;
579
+ const filterValue = filterField ? currentFilters[filterField] ?? "" : "";
580
+ return (_jsx("th", { className: cn("px-3 py-2 align-top", showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]"), children: column.filter && filterField ? (_jsx("input", { value: filterValue, onChange: (event) => {
581
+ const nextFilters = {
582
+ ...currentFilters,
583
+ [filterField]: event.target.value
584
+ };
585
+ const normalized = normalizeFilters(nextFilters);
586
+ commitFilters(normalized, currentGlobalFilter);
587
+ }, placeholder: column.filterPlaceholder ?? t(i18n, "components.datatable.columnFilterPlaceholder", { column: String(column.header ?? "") }), className: "w-full rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))] placeholder:text-[rgb(var(--sg-input-placeholder,var(--sg-muted)))] outline-none focus:ring-2 focus:ring-[rgb(var(--sg-ring))]" })) : null }, `filter-${column.columnId ?? column.field ?? columnIndex}`));
588
+ }) })) : null] }), _jsx("tbody", { children: loading ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: loadingLabel }) })) : pagedRows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, visibleColumns.length), className: "px-4 py-6 text-center text-sm text-[rgb(var(--sg-muted))]", children: emptyLabel }) })) : (pagedRows.map((rowData, rowIndex) => {
589
+ const absoluteRowIndex = safeFirst + rowIndex;
590
+ const selected = isRowSelected(rowData);
591
+ const customRowClass = typeof rowClassName === "function" ? rowClassName(rowData, absoluteRowIndex) : rowClassName;
592
+ return (_jsx("tr", { "aria-selected": selected || undefined, onClick: (event) => {
593
+ const target = event.target;
594
+ if (target.closest("button,a,input,select,textarea,label,[data-sg-stop-row-select='true']")) {
595
+ return;
596
+ }
597
+ handleRowSelection(rowData);
598
+ }, className: cn(selectionMode ? "cursor-pointer" : "", stripedRows && absoluteRowIndex % 2 === 1 ? "bg-[rgb(var(--sg-primary-50))]" : "", hoverableRows ? "hover:bg-[rgb(var(--sg-primary-100))]" : "", selected ? "bg-[rgb(var(--sg-primary-100))]" : "", customRowClass), children: visibleColumns.map((column, columnIndex) => {
599
+ const cellField = column.field;
600
+ const cellValue = getFieldValue(rowData, cellField);
601
+ const customCellClass = typeof column.bodyClassName === "function"
602
+ ? column.bodyClassName(rowData, absoluteRowIndex)
603
+ : column.bodyClassName;
604
+ const renderedValue = column.body
605
+ ? column.body(rowData, {
606
+ rowData,
607
+ rowIndex: absoluteRowIndex,
608
+ field: cellField,
609
+ value: cellValue
610
+ })
611
+ : (_jsx("span", { children: cellValue === null || cellValue === undefined ? "-" : String(cellValue) }));
612
+ return (_jsx("td", { className: cn("px-3 py-2 text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-b border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-b border-[rgb(var(--sg-border))]", column.className, customCellClass), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: renderedValue }, `cell-${column.columnId ?? cellField ?? columnIndex}-${absoluteRowIndex}`));
613
+ }) }, String(getRowIdentity(rowData, dataKey) ?? absoluteRowIndex)));
614
+ })) }), hasFooter ? (_jsx("tfoot", { children: _jsx("tr", { className: "bg-[rgb(var(--sg-primary-50))]", children: visibleColumns.map((column, columnIndex) => {
615
+ const footerValue = typeof column.footer === "function" ? column.footer(sortedRows) : column.footer;
616
+ return (_jsx("td", { className: cn("px-3 py-2 font-semibold text-[rgb(var(--sg-text))]", resolveAlignmentClass(column.align), showGridlines ? "border-t border-r border-[rgb(var(--sg-border))] last:border-r-0" : "border-t border-[rgb(var(--sg-border))]", column.className), style: { width: toCssSize(column.width), minWidth: toCssSize(column.minWidth) }, children: footerValue ?? null }, `foot-${column.columnId ?? column.field ?? columnIndex}`));
617
+ }) }) })) : null] }) })] }), paginator ? (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage <= 1, onClick: () => goToPage(currentPage - 1), children: prevLabel }), pageWindow.map((pageNumber) => (_jsx(SgButton, { size: "sm", appearance: pageNumber === currentPage ? "solid" : "outline", onClick: () => goToPage(pageNumber), children: String(pageNumber) }, `page-${pageNumber}`))), _jsx(SgButton, { size: "sm", appearance: "outline", disabled: currentPage >= pageCount, onClick: () => goToPage(currentPage + 1), children: nextLabel }), _jsx("span", { className: "min-w-[180px] text-xs text-[rgb(var(--sg-muted))] md:ml-auto", children: pageReport }), rowsPerPageOptions && rowsPerPageOptions.length > 0 ? (_jsxs("label", { className: "ml-auto inline-flex items-center gap-2 text-xs text-[rgb(var(--sg-muted))] md:ml-0", children: [_jsx("span", { children: rowsPerPageLabel }), _jsx("select", { value: currentRows, onChange: (event) => {
437
618
  const nextRows = Number(event.target.value) || currentRows;
438
619
  commitPage(0, nextRows);
439
620
  }, className: "rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-input-bg,var(--sg-surface)))] px-2 py-1 text-xs text-[rgb(var(--sg-input-fg,var(--sg-text)))]", children: rowsPerPageOptions.map((option) => (_jsx("option", { value: option, children: option }, option))) })] })) : null] })) : null] }) }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"SgInputText.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputText.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAGlF,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC,sBAAsB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,GAAG;QAC1D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;KACnC,CAAC,CAAC;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,WAAW,CAAC,CAAC;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACjD,CAAC;AAyeF,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CAsElD"}
1
+ {"version":3,"file":"SgInputText.d.ts","sourceRoot":"","sources":["../../src/inputs/SgInputText.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAGlF,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC,sBAAsB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,GAAG;QAC1D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;KACnC,CAAC,CAAC;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,WAAW,CAAC,CAAC;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACjD,CAAC;AAohBF,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CAsElD"}
@@ -120,13 +120,16 @@ function SgInputTextBase(props) {
120
120
  const value = stripAffixes(inputProps.value ?? inputProps.defaultValue ?? "");
121
121
  return value.length;
122
122
  });
123
- React.useEffect(() => {
124
- const next = (inputRef.current?.value ?? "").length > 0;
125
- if (next !== isFilled)
126
- setIsFilled(next);
127
- const nextLength = (inputRef.current?.value ?? "").length;
123
+ const syncFilledStateFromDom = React.useCallback(() => {
124
+ const nextValue = inputRef.current?.value ?? "";
125
+ const nextFilled = nextValue.length > 0;
126
+ const nextLength = nextValue.length;
127
+ setIsFilled((prev) => (prev === nextFilled ? prev : nextFilled));
128
128
  setValueLength((prev) => (prev === nextLength ? prev : nextLength));
129
- }, [isFilled]);
129
+ }, []);
130
+ React.useEffect(() => {
131
+ syncFilledStateFromDom();
132
+ }, [syncFilledStateFromDom]);
130
133
  React.useEffect(() => {
131
134
  if (inputProps.value === undefined)
132
135
  return;
@@ -134,6 +137,27 @@ function SgInputTextBase(props) {
134
137
  setIsFilled(raw.length > 0);
135
138
  setValueLength(raw.length);
136
139
  }, [inputProps.value, stripAffixes]);
140
+ React.useEffect(() => {
141
+ const node = inputRef.current;
142
+ if (!node)
143
+ return;
144
+ const sync = () => {
145
+ syncFilledStateFromDom();
146
+ };
147
+ // Browsers/password managers may hydrate the value without dispatching React events.
148
+ const timers = [
149
+ window.setTimeout(sync, 0),
150
+ window.setTimeout(sync, 100),
151
+ window.setTimeout(sync, 300)
152
+ ];
153
+ node.addEventListener("input", sync);
154
+ node.addEventListener("change", sync);
155
+ return () => {
156
+ timers.forEach((timer) => window.clearTimeout(timer));
157
+ node.removeEventListener("input", sync);
158
+ node.removeEventListener("change", sync);
159
+ };
160
+ }, [syncFilledStateFromDom]);
137
161
  React.useLayoutEffect(() => {
138
162
  if (prefixRef.current) {
139
163
  const next = prefixRef.current.offsetWidth;
@@ -222,6 +246,7 @@ function SgInputTextBase(props) {
222
246
  props.onExit?.();
223
247
  };
224
248
  const handleFocus = () => {
249
+ syncFilledStateFromDom();
225
250
  props.onEnter?.();
226
251
  };
227
252
  const handleClear = () => {
@@ -316,7 +341,17 @@ function SgInputTextBase(props) {
316
341
  const outerLayoutStyle = labelPosition === "left"
317
342
  ? { ["--sg-input-label-width"]: resolvedLabelWidth }
318
343
  : undefined;
319
- const fieldNode = (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative", children: [prefixText ? (_jsx("span", { ref: prefixRef, className: "pointer-events-none absolute left-0 top-0 z-10 flex h-11 items-center rounded-l-md border border-border bg-muted/40 px-3 text-xs leading-none text-foreground/70", children: prefixText })) : null, props.prefixIcon ? (_jsx("span", { className: "pointer-events-none absolute left-3 top-1/2 z-10 -translate-y-1/2 text-foreground/60", children: props.prefixIcon })) : null, _jsx("input", { id: props.id, type: props.type ?? "text", placeholder: placeholder, className: props.className ?? finalClass, style: {
344
+ const fieldNode = (_jsxs(_Fragment, { children: [_jsx("style", { children: `
345
+ @keyframes sg-input-autofill-detect {
346
+ from {}
347
+ to {}
348
+ }
349
+
350
+ input:-webkit-autofill {
351
+ animation-name: sg-input-autofill-detect;
352
+ animation-duration: 0.01s;
353
+ }
354
+ ` }), _jsxs("div", { className: "relative", children: [prefixText ? (_jsx("span", { ref: prefixRef, className: "pointer-events-none absolute left-0 top-0 z-10 flex h-11 items-center rounded-l-md border border-border bg-muted/40 px-3 text-xs leading-none text-foreground/70", children: prefixText })) : null, props.prefixIcon ? (_jsx("span", { className: "pointer-events-none absolute left-3 top-1/2 z-10 -translate-y-1/2 text-foreground/60", children: props.prefixIcon })) : null, _jsx("input", { id: props.id, type: props.type ?? "text", placeholder: placeholder, className: props.className ?? finalClass, style: {
320
355
  borderRadius: resolvedBorderRadius,
321
356
  paddingLeft: prefixPaddingStyle,
322
357
  paddingRight: suffixPaddingStyle,
@@ -332,7 +367,7 @@ function SgInputTextBase(props) {
332
367
  ...(prefixText ? { borderTopLeftRadius: 0, borderBottomLeftRadius: 0, borderLeftWidth: 0 } : {}),
333
368
  ...(suffixText ? { borderTopRightRadius: 0, borderBottomRightRadius: 0, borderRightWidth: 0 } : {}),
334
369
  ...(resolvedInputProps.style ?? {})
335
- }, maxLength: props.maxLength, readOnly: props.readOnly, disabled: props.enabled === false, inputMode: props.textInputType ?? resolvedInputProps.inputMode, ...resolvedInputProps, ref: setRefs, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus }), suffixText ? (_jsx("span", { ref: suffixRef, className: "pointer-events-none absolute right-0 top-0 z-10 flex h-11 items-center rounded-r-md border border-border bg-muted/40 px-3 text-xs leading-none text-foreground/70", children: suffixText })) : null, isFloatLabel ? (_jsxs("label", { htmlFor: props.id, className: [
370
+ }, maxLength: props.maxLength, readOnly: props.readOnly, disabled: props.enabled === false, inputMode: props.textInputType ?? resolvedInputProps.inputMode, ...resolvedInputProps, ref: setRefs, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, onAnimationStart: syncFilledStateFromDom }), suffixText ? (_jsx("span", { ref: suffixRef, className: "pointer-events-none absolute right-0 top-0 z-10 flex h-11 items-center rounded-r-md border border-border bg-muted/40 px-3 text-xs leading-none text-foreground/70", children: suffixText })) : null, isFloatLabel ? (_jsxs("label", { htmlFor: props.id, className: [
336
371
  "absolute z-10 bg-[var(--sg-input-bg,hsl(var(--background)))] px-1 transition-all",
337
372
  isFilled ? "-top-2 text-xs" : "top-3 text-sm",
338
373
  hasError ? "text-[hsl(var(--destructive))]" : isFilled ? "text-[hsl(var(--primary))]" : "text-foreground/60",
@@ -1 +1 @@
1
- {"version":3,"file":"SgScreen.d.ts","sourceRoot":"","sources":["../../src/layout/SgScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,2CA8EtD;yBA9Ee,QAAQ"}
1
+ {"version":3,"file":"SgScreen.d.ts","sourceRoot":"","sources":["../../src/layout/SgScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,2CA0CtD;yBA1Ce,QAAQ"}
@@ -1,46 +1,19 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import * as React from "react";
4
3
  import { cn, renderDockContent, toCssSpace } from "./sgDocking";
5
4
  export function SgScreen(props) {
6
5
  const { fullscreen = true, width, height, padding, className, style, children, ...rest } = props;
7
- const ref = React.useRef(null);
8
- const [measuredSize, setMeasuredSize] = React.useState({});
9
- React.useLayoutEffect(() => {
10
- if (!fullscreen) {
11
- setMeasuredSize({});
12
- return;
13
- }
14
- const element = ref.current;
15
- const parent = element?.parentElement;
16
- if (!element || !parent)
17
- return;
18
- const update = () => {
19
- setMeasuredSize({
20
- width: parent.clientWidth || undefined,
21
- height: parent.clientHeight || undefined
22
- });
23
- };
24
- update();
25
- const observer = new ResizeObserver(update);
26
- observer.observe(parent);
27
- window.addEventListener("resize", update);
28
- return () => {
29
- observer.disconnect();
30
- window.removeEventListener("resize", update);
31
- };
32
- }, [fullscreen]);
33
- return (_jsx("div", { ref: ref, className: cn("relative box-border flex flex-1 self-stretch min-h-0 min-w-0 max-h-full max-w-full overflow-hidden", className), style: {
6
+ return (_jsx("div", { className: cn("relative box-border flex flex-1 self-stretch min-h-0 min-w-0 max-h-full max-w-full overflow-hidden", className), style: {
34
7
  ...style,
35
8
  ...(width !== undefined
36
9
  ? { width: toCssSpace(width) }
37
- : fullscreen && measuredSize.width !== undefined
38
- ? { width: `${measuredSize.width}px` }
10
+ : fullscreen
11
+ ? { width: "100%" }
39
12
  : null),
40
13
  ...(height !== undefined
41
14
  ? { height: toCssSpace(height) }
42
- : fullscreen && measuredSize.height !== undefined
43
- ? { height: `${measuredSize.height}px` }
15
+ : fullscreen
16
+ ? { height: "100dvh" }
44
17
  : null),
45
18
  padding: toCssSpace(padding)
46
19
  }, ...rest, children: _jsx("div", { className: "flex flex-1 min-h-0 min-w-0 flex-col", children: renderDockContent({
@@ -71,7 +71,7 @@ function renderDockItem(item, index, axis) {
71
71
  ...(item.minHeightPx !== undefined ? { minHeight: `${item.minHeightPx}px` } : null),
72
72
  ...(heightCss !== undefined
73
73
  ? { height: heightCss, flex: `0 0 ${heightCss}` }
74
- : { height: "100%", flex: "1 1 0%" })
74
+ : { height: "auto", flex: "0 0 auto" })
75
75
  }, "w-full min-w-0");
76
76
  }
77
77
  if (axis === "left" || axis === "right") {
@@ -83,7 +83,7 @@ function renderDockItem(item, index, axis) {
83
83
  ...(item.minWidthPx !== undefined ? { minWidth: `${item.minWidthPx}px` } : null),
84
84
  ...(widthCss !== undefined
85
85
  ? { width: widthCss, flex: `0 0 ${widthCss}` }
86
- : { width: "100%", flex: "1 1 0%" })
86
+ : { width: "auto", flex: "0 0 auto" })
87
87
  }, "h-full min-h-0 min-w-0");
88
88
  }
89
89
  return cloneWithLayout(item.node, item.key ?? `client-${index}`, {
@@ -1 +1 @@
1
- {"version":3,"file":"SgConfirmationDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgConfirmationDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEjF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,aAAa,EACb,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,eAAe,CAC1E,GAAG;IACF,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,WAAW,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,gCAAgC,CAAC;IAChD,aAAa,CAAC,EAAE,gCAAgC,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAoEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,yBAAyB,CAAC,2CA2I9E;yBA3Ie,oBAAoB"}
1
+ {"version":3,"file":"SgConfirmationDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgConfirmationDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEjF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,aAAa,EACb,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,eAAe,CAC1E,GAAG;IACF,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,WAAW,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,gCAAgC,CAAC;IAChD,aAAa,CAAC,EAAE,gCAAgC,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAoEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,yBAAyB,CAAC,2CA2J9E;yBA3Je,oBAAoB"}
@@ -75,7 +75,21 @@ export function SgConfirmationDialog(props) {
75
75
  const resolvedIcon = icon !== undefined ? icon : defaultSeverityIcon(severity);
76
76
  const cancelSeverity = cancelButton?.severity ?? "secondary";
77
77
  const confirmSeverity = confirmButton?.severity ?? resolveButtonSeverity(severity, "primary");
78
+ const resolvedCancelCustomColors = cancelButton?.appearance === undefined &&
79
+ cancelButton?.severity === undefined &&
80
+ cancelButton?.className === undefined
81
+ ? {
82
+ // SgButton outline uses `bg` as the text color token, so keep it visible here.
83
+ bg: "hsl(var(--foreground))",
84
+ fg: "hsl(var(--foreground))",
85
+ border: "hsl(var(--border))",
86
+ hoverBg: "hsl(var(--muted) / 0.8)",
87
+ hoverFg: "hsl(var(--foreground))",
88
+ hoverBorder: "hsl(var(--border))",
89
+ activeBg: "hsl(var(--muted))",
90
+ }
91
+ : undefined;
78
92
  const messageBlock = (_jsx("div", { className: "text-sm text-muted-foreground", children: message }));
79
- return (_jsx(SgDialog, { ...dialogProps, open: open, onOpenChange: handleDialogOpenChange, onClose: onClose, closeable: closeable, severity: severity, showTopAccent: showSeverityAccent, customColor: customColor, elevation: elevation, title: title, size: size, footer: (_jsxs(_Fragment, { children: [_jsx(SgButton, { size: "sm", appearance: cancelButton?.appearance ?? "ghost", severity: cancelSeverity, shape: cancelButton?.shape ?? "rounded", disabled: cancelButton?.disabled, className: cancelButton?.className, leftIcon: cancelIcon, onClick: handleCancel, children: cancelLabel }), _jsx(SgButton, { size: "sm", appearance: confirmButton?.appearance ?? "solid", severity: confirmSeverity, shape: confirmButton?.shape ?? "rounded", disabled: confirmButton?.disabled, className: confirmButton?.className, leftIcon: confirmIcon, onClick: handleConfirm, children: confirmLabel })] })), children: resolvedIcon ? (iconPlacement === "top" ? (_jsxs("div", { className: "flex flex-col items-start gap-3", children: [_jsx("div", { className: "shrink-0", children: resolvedIcon }), messageBlock] })) : (_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "shrink-0", children: resolvedIcon }), _jsx("div", { className: "min-w-0", children: messageBlock })] }))) : (messageBlock) }));
93
+ return (_jsx(SgDialog, { ...dialogProps, open: open, onOpenChange: handleDialogOpenChange, onClose: onClose, closeable: closeable, severity: severity, showTopAccent: showSeverityAccent, customColor: customColor, elevation: elevation, title: title, size: size, footer: (_jsxs(_Fragment, { children: [_jsx(SgButton, { size: "sm", appearance: cancelButton?.appearance ?? "outline", severity: cancelSeverity, shape: cancelButton?.shape ?? "rounded", disabled: cancelButton?.disabled, className: cancelButton?.className, customColors: resolvedCancelCustomColors, leftIcon: cancelIcon, onClick: handleCancel, children: cancelLabel }), _jsx(SgButton, { size: "sm", appearance: confirmButton?.appearance ?? "solid", severity: confirmSeverity, shape: confirmButton?.shape ?? "rounded", disabled: confirmButton?.disabled, className: confirmButton?.className, leftIcon: confirmIcon, onClick: handleConfirm, children: confirmLabel })] })), children: resolvedIcon ? (iconPlacement === "top" ? (_jsxs("div", { className: "flex flex-col items-start gap-3", children: [_jsx("div", { className: "shrink-0", children: resolvedIcon }), messageBlock] })) : (_jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "shrink-0", children: resolvedIcon }), _jsx("div", { className: "min-w-0", children: messageBlock })] }))) : (messageBlock) }));
80
94
  }
81
95
  SgConfirmationDialog.displayName = "SgConfirmationDialog";
@@ -1 +1 @@
1
- {"version":3,"file":"SgDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3E,gCAAgC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAsRF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,4BA6QtD;yBA7Qe,QAAQ"}
1
+ {"version":3,"file":"SgDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3E,gCAAgC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAsRF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,4BAqRtD;yBArRe,QAAQ"}