@simpleapps-com/augur-web 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{chunk-NSSX7USQ.cjs → chunk-I5NVZORX.cjs} +4 -3
  2. package/dist/chunk-I5NVZORX.cjs.map +1 -0
  3. package/dist/{chunk-3VN3FX2Q.js → chunk-OJ5G4BLS.js} +4 -3
  4. package/dist/chunk-OJ5G4BLS.js.map +1 -0
  5. package/dist/command.cjs +6 -2
  6. package/dist/command.cjs.map +1 -1
  7. package/dist/command.d.cts +5 -2
  8. package/dist/command.d.ts +5 -2
  9. package/dist/command.js +7 -3
  10. package/dist/command.js.map +1 -1
  11. package/dist/confirm-dialog.cjs +1 -1
  12. package/dist/confirm-dialog.cjs.map +1 -1
  13. package/dist/confirm-dialog.js +1 -1
  14. package/dist/confirm-dialog.js.map +1 -1
  15. package/dist/data-table.cjs +16 -16
  16. package/dist/data-table.cjs.map +1 -1
  17. package/dist/data-table.js +15 -15
  18. package/dist/data-table.js.map +1 -1
  19. package/dist/detail-panel.cjs +3 -3
  20. package/dist/detail-panel.cjs.map +1 -1
  21. package/dist/detail-panel.js +3 -3
  22. package/dist/pagination.cjs +2 -2
  23. package/dist/pagination.js +1 -1
  24. package/dist/price-format.cjs +27 -5
  25. package/dist/price-format.cjs.map +1 -1
  26. package/dist/price-format.js +26 -4
  27. package/dist/price-format.js.map +1 -1
  28. package/dist/price.cjs +31 -5
  29. package/dist/price.cjs.map +1 -1
  30. package/dist/price.d.cts +15 -3
  31. package/dist/price.d.ts +15 -3
  32. package/dist/price.js +29 -3
  33. package/dist/price.js.map +1 -1
  34. package/package.json +6 -6
  35. package/dist/chunk-3VN3FX2Q.js.map +0 -1
  36. package/dist/chunk-DZDC4HHK.js +0 -33
  37. package/dist/chunk-DZDC4HHK.js.map +0 -1
  38. package/dist/chunk-NSSX7USQ.cjs.map +0 -1
  39. package/dist/chunk-VLZDTWPR.cjs +0 -33
  40. package/dist/chunk-VLZDTWPR.cjs.map +0 -1
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-XIKSI7NY.js";
11
11
  import {
12
12
  ListPagination
13
- } from "./chunk-3VN3FX2Q.js";
13
+ } from "./chunk-OJ5G4BLS.js";
14
14
  import {
15
15
  Select,
16
16
  SelectContent,
@@ -43,6 +43,7 @@ import {
43
43
  import * as React from "react";
44
44
  import {
45
45
  flexRender,
46
+ functionalUpdate,
46
47
  getCoreRowModel,
47
48
  getSortedRowModel,
48
49
  getFilteredRowModel,
@@ -140,20 +141,21 @@ function ColumnToggle({ table }) {
140
141
  ] });
141
142
  }
142
143
  function HeaderCell({ header }) {
143
- return /* @__PURE__ */ jsx(
144
- TableHead,
144
+ const canSort = header.column.getCanSort();
145
+ const sorted = header.column.getIsSorted();
146
+ const ariaSort = canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0;
147
+ return /* @__PURE__ */ jsx(TableHead, { className: getAlignCn(header.column.columnDef.meta), "aria-sort": ariaSort, children: canSort ? /* @__PURE__ */ jsxs(
148
+ "button",
145
149
  {
146
- className: cn(
147
- getAlignCn(header.column.columnDef.meta),
148
- header.column.getCanSort() && "cursor-pointer select-none"
149
- ),
150
+ type: "button",
150
151
  onClick: header.column.getToggleSortingHandler(),
151
- children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
152
+ className: "inline-flex cursor-pointer select-none items-center gap-1",
153
+ children: [
152
154
  flexRender(header.column.columnDef.header, header.getContext()),
153
- header.column.getCanSort() && /* @__PURE__ */ jsx(SortIndicator, { direction: header.column.getIsSorted() })
154
- ] })
155
+ /* @__PURE__ */ jsx(SortIndicator, { direction: sorted })
156
+ ]
155
157
  }
156
- );
158
+ ) : /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1", children: flexRender(header.column.columnDef.header, header.getContext()) }) });
157
159
  }
158
160
  function DataCell({ cell }) {
159
161
  return /* @__PURE__ */ jsx(TableCell, { className: getAlignCn(cell.column.columnDef.meta), children: flexRender(cell.column.columnDef.cell, cell.getContext()) });
@@ -289,13 +291,11 @@ function useDataTable(opts) {
289
291
  const globalFilter = opts.externalGlobalFilter ?? internalGlobalFilter;
290
292
  const rowSelectionState = opts.externalRowSelection ?? internalRowSelection;
291
293
  const handleSortingChange = opts.onSortingChange ? (updater) => {
292
- opts.onSortingChange(updater(sorting));
294
+ opts.onSortingChange(functionalUpdate(updater, sorting));
293
295
  } : setInternalSorting;
294
296
  const handleGlobalFilterChange = opts.onGlobalFilterChange ?? setInternalGlobalFilter;
295
297
  const handleRowSelectionChange = opts.onRowSelectionChange ? (updater) => {
296
- opts.onRowSelectionChange(
297
- updater(rowSelectionState)
298
- );
298
+ opts.onRowSelectionChange(functionalUpdate(updater, rowSelectionState));
299
299
  } : setInternalRowSelection;
300
300
  const tanstackColumns = React.useMemo(
301
301
  () => buildTanstackColumns(opts.columns, opts.selectable),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["/** Feature-complete admin data table built on TanStack Table. */\n\"use client\";\n\nimport * as React from \"react\";\nimport {\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n useReactTable,\n type ColumnDef as TanstackColumnDef,\n type SortingState,\n type RowSelectionState,\n type VisibilityState,\n type Table as TanstackTable,\n type Header,\n type Row,\n type Cell,\n} from \"@tanstack/react-table\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { LuArrowDown, LuArrowUp, LuArrowUpDown, LuDownload, LuSettings2 } from \"react-icons/lu\";\nimport { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"./table\";\nimport { Input } from \"./input\";\nimport { Spinner } from \"./spinner\";\nimport { Checkbox } from \"./checkbox\";\nimport { Button } from \"./button\";\nimport { ListPagination } from \"./pagination\";\nimport { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from \"./select\";\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuCheckboxItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n} from \"./dropdown-menu\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ColumnDef<T> {\n key: keyof T & string;\n header: string;\n sortable?: boolean;\n render?: (row: T) => React.ReactNode;\n align?: \"left\" | \"center\" | \"right\";\n hideable?: boolean;\n}\n\nexport interface DataTablePagination {\n page: number;\n totalPages: number;\n getHref: (page: number) => string;\n onPageChange?: (page: number) => void;\n /** Current page size. Required when pageSizeOptions is set. */\n pageSize?: number;\n /** Available page size options. Renders a dropdown when provided. */\n pageSizeOptions?: number[];\n /** Called when the user selects a different page size. */\n onPageSizeChange?: (size: number) => void;\n}\n\nexport interface DataTableProps<T> {\n columns: ColumnDef<T>[];\n data: T[];\n searchable?: boolean;\n searchPlaceholder?: string;\n onRowClick?: (row: T) => void;\n loading?: boolean;\n emptyMessage?: string;\n toolbar?: React.ReactNode;\n className?: string;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n globalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n sortingState?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n selectable?: boolean;\n rowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n bulkActions?: (selectedRows: T[]) => React.ReactNode;\n columnToggle?: boolean;\n exportCsv?: boolean;\n csvFilename?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst ALIGN_CLASS = { left: \"text-left\", center: \"text-center\", right: \"text-right\" } as const;\n\nfunction getAlignCn(meta: unknown): string {\n const align = (meta as { align?: string } | undefined)?.align ?? \"left\";\n return ALIGN_CLASS[align as keyof typeof ALIGN_CLASS];\n}\n\nfunction buildTanstackColumns<T>(\n columns: ColumnDef<T>[],\n selectable: boolean,\n): TanstackColumnDef<T, unknown>[] {\n const cols: TanstackColumnDef<T, unknown>[] = [];\n if (selectable) {\n cols.push({\n id: \"_select\",\n header: ({ table }) => (\n <Checkbox\n checked={table.getIsAllPageRowsSelected()}\n onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}\n aria-label=\"Select all\"\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n checked={row.getIsSelected()}\n onCheckedChange={(v) => row.toggleSelected(!!v)}\n aria-label=\"Select row\"\n onClick={(e) => e.stopPropagation()}\n />\n ),\n enableSorting: false,\n enableHiding: false,\n meta: { align: \"center\" },\n });\n }\n for (const col of columns) {\n cols.push({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n enableSorting: col.sortable ?? false,\n enableHiding: col.hideable !== false,\n cell: col.render\n ? (info) => col.render!(info.row.original)\n : (info) => String(info.getValue() ?? \"\"),\n meta: { align: col.align },\n });\n }\n return cols;\n}\n\nfunction exportToCsv<T>(columns: ColumnDef<T>[], data: T[], filename: string) {\n const headers = columns.map((c) => c.header);\n const rows = data.map((row) =>\n columns.map((col) => {\n const str = String(row[col.key] ?? \"\");\n return str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")\n ? `\"${str.replace(/\"/g, '\"\"')}\"`\n : str;\n }),\n );\n const csv = [headers.join(\",\"), ...rows.map((r) => r.join(\",\"))].join(\"\\n\");\n const blob = new Blob([csv], { type: \"text/csv;charset=utf-8;\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = `${filename}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction SortIndicator({ direction }: { direction: false | \"asc\" | \"desc\" }) {\n if (direction === \"asc\") return <LuArrowUp className=\"h-4 w-4\" />;\n if (direction === \"desc\") return <LuArrowDown className=\"h-4 w-4\" />;\n return <LuArrowUpDown className=\"text-muted-foreground/50 h-4 w-4\" />;\n}\n\nfunction ColumnToggle<T>({ table }: { table: TanstackTable<T> }) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <LuSettings2 className=\"mr-2 h-4 w-4\" />\n Columns\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {table\n .getAllColumns()\n .filter((col) => col.getCanHide())\n .map((col) => (\n <DropdownMenuCheckboxItem\n key={col.id}\n checked={col.getIsVisible()}\n onCheckedChange={(v) => col.toggleVisibility(!!v)}\n >\n {col.columnDef.header as string}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction HeaderCell<T>({ header }: { header: Header<T, unknown> }) {\n return (\n <TableHead\n className={cn(\n getAlignCn(header.column.columnDef.meta),\n header.column.getCanSort() && \"cursor-pointer select-none\",\n )}\n onClick={header.column.getToggleSortingHandler()}\n >\n <span className=\"inline-flex items-center gap-1\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getCanSort() && <SortIndicator direction={header.column.getIsSorted()} />}\n </span>\n </TableHead>\n );\n}\n\nfunction DataCell<T>({ cell }: { cell: Cell<T, unknown> }) {\n return (\n <TableCell className={getAlignCn(cell.column.columnDef.meta)}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n );\n}\n\nfunction DataRow<T>({ row, onRowClick }: { row: Row<T>; onRowClick?: (r: T) => void }) {\n return (\n <TableRow\n data-state={row.getIsSelected() ? \"selected\" : undefined}\n className={cn(onRowClick && \"cursor-pointer\")}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => (\n <DataCell key={cell.id} cell={cell} />\n ))}\n </TableRow>\n );\n}\n\nfunction ExportButton<T>({\n columns,\n data,\n csvFilename,\n}: {\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n}) {\n return (\n <Button variant=\"outline\" size=\"sm\" onClick={() => exportToCsv(columns, data, csvFilename)}>\n <LuDownload className=\"mr-2 h-4 w-4\" />\n Export\n </Button>\n );\n}\n\nfunction BulkActionsBar<T>({\n selectedRows,\n bulkActions,\n}: {\n selectedRows: T[];\n bulkActions: (rows: T[]) => React.ReactNode;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">{selectedRows.length} selected</span>\n {bulkActions(selectedRows)}\n </div>\n );\n}\n\nfunction Toolbar<T>({\n searchable,\n searchPlaceholder,\n globalFilter,\n onGlobalFilterChange,\n selectedRows,\n bulkActions,\n toolbar,\n exportCsv,\n columns,\n data,\n csvFilename,\n columnToggle,\n table,\n}: {\n searchable: boolean;\n searchPlaceholder: string;\n globalFilter: string;\n onGlobalFilterChange: (value: string) => void;\n selectedRows: T[];\n bulkActions?: (rows: T[]) => React.ReactNode;\n toolbar?: React.ReactNode;\n exportCsv: boolean;\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n columnToggle: boolean;\n table: TanstackTable<T>;\n}) {\n const hasSelection = selectedRows.length > 0;\n return (\n <div className=\"flex items-center gap-4\">\n {searchable && (\n <Input\n placeholder={searchPlaceholder}\n value={globalFilter}\n onChange={(e) => onGlobalFilterChange(e.target.value)}\n className=\"max-w-sm\"\n />\n )}\n {hasSelection && bulkActions && (\n <BulkActionsBar selectedRows={selectedRows} bulkActions={bulkActions} />\n )}\n <div className=\"ml-auto flex items-center gap-2\">\n {toolbar}\n {exportCsv && <ExportButton columns={columns} data={data} csvFilename={csvFilename} />}\n {columnToggle && <ColumnToggle table={table} />}\n </div>\n </div>\n );\n}\n\nfunction TableBodyContent<T>({\n loading,\n colSpan,\n emptyMessage,\n rows,\n onRowClick,\n}: {\n loading: boolean;\n colSpan: number;\n emptyMessage: string;\n rows: Row<T>[];\n onRowClick?: (r: T) => void;\n}) {\n if (loading) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n <Spinner size=\"lg\" className=\"mx-auto\" />\n </TableCell>\n </TableRow>\n );\n }\n if (rows.length === 0) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n {emptyMessage}\n </TableCell>\n </TableRow>\n );\n }\n return (\n <>\n {rows.map((row) => (\n <DataRow key={row.id} row={row} onRowClick={onRowClick} />\n ))}\n </>\n );\n}\n\nfunction PageSizeSelector({\n pageSize,\n options,\n onChange,\n}: {\n pageSize: number;\n options: number[];\n onChange: (size: number) => void;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">Rows per page</span>\n <Select value={String(pageSize)} onValueChange={(v) => onChange(Number(v))}>\n <SelectTrigger className=\"h-8 w-[70px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map((size) => (\n <SelectItem key={size} value={String(size)}>\n {size}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n}\n\nfunction PaginationFooter({ pagination }: { pagination?: DataTablePagination }) {\n if (!pagination) return null;\n const showPageSize =\n pagination.pageSizeOptions && pagination.pageSize !== undefined && pagination.onPageSizeChange;\n const showPages = pagination.totalPages > 1;\n if (!showPageSize && !showPages) return null;\n return (\n <div className=\"flex items-center justify-between\">\n {showPageSize ? (\n <PageSizeSelector\n pageSize={pagination.pageSize!}\n options={pagination.pageSizeOptions!}\n onChange={pagination.onPageSizeChange!}\n />\n ) : (\n <div />\n )}\n {showPages && (\n <ListPagination\n page={pagination.page}\n totalPages={pagination.totalPages}\n getHref={pagination.getHref}\n onPageChange={pagination.onPageChange}\n />\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook: encapsulates all state management and TanStack Table configuration\n// ---------------------------------------------------------------------------\n\ninterface UseDataTableOptions<T> {\n columns: ColumnDef<T>[];\n data: T[];\n selectable: boolean;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n externalGlobalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n externalSorting?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n externalRowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n}\n\nfunction useDataTable<T>(opts: UseDataTableOptions<T>) {\n const isManualFiltering = opts.externalGlobalFilter !== undefined;\n const isManualSorting = opts.externalSorting !== undefined;\n\n const [internalSorting, setInternalSorting] = React.useState<SortingState>([]);\n const [internalGlobalFilter, setInternalGlobalFilter] = React.useState(\"\");\n const [internalRowSelection, setInternalRowSelection] = React.useState<RowSelectionState>({});\n const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});\n\n const sorting = opts.externalSorting ?? internalSorting;\n const globalFilter = opts.externalGlobalFilter ?? internalGlobalFilter;\n const rowSelectionState = opts.externalRowSelection ?? internalRowSelection;\n\n const handleSortingChange = opts.onSortingChange\n ? (updater: SortingState | ((prev: SortingState) => SortingState)) => {\n opts.onSortingChange!((updater as (prev: SortingState) => SortingState)(sorting));\n }\n : setInternalSorting;\n\n const handleGlobalFilterChange = opts.onGlobalFilterChange ?? setInternalGlobalFilter;\n\n const handleRowSelectionChange = opts.onRowSelectionChange\n ? (updater: RowSelectionState | ((prev: RowSelectionState) => RowSelectionState)) => {\n opts.onRowSelectionChange!(\n (updater as (prev: RowSelectionState) => RowSelectionState)(rowSelectionState),\n );\n }\n : setInternalRowSelection;\n\n const tanstackColumns = React.useMemo(\n () => buildTanstackColumns(opts.columns, opts.selectable),\n [opts.columns, opts.selectable],\n );\n\n const table = useReactTable({\n data: opts.data,\n columns: tanstackColumns,\n state: {\n sorting,\n globalFilter: isManualFiltering ? undefined : globalFilter,\n rowSelection: rowSelectionState,\n columnVisibility,\n },\n onSortingChange: handleSortingChange,\n onGlobalFilterChange: isManualFiltering ? undefined : setInternalGlobalFilter,\n onRowSelectionChange: handleRowSelectionChange,\n onColumnVisibilityChange: setColumnVisibility,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: isManualSorting ? undefined : getSortedRowModel(),\n getFilteredRowModel: isManualFiltering ? undefined : getFilteredRowModel(),\n manualSorting: isManualSorting,\n manualFiltering: isManualFiltering,\n manualPagination: opts.pagination !== undefined,\n enableRowSelection: opts.selectable,\n getRowId: opts.getRowId ? (row) => opts.getRowId!(row) : undefined,\n });\n\n const selectedRows = opts.selectable\n ? table.getSelectedRowModel().rows.map((r) => r.original)\n : [];\n\n return { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows };\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nfunction DataTable<T>({\n columns,\n data,\n searchable = false,\n searchPlaceholder = \"Search...\",\n onRowClick,\n loading = false,\n emptyMessage = \"No results.\",\n toolbar,\n className,\n getRowId,\n pagination,\n globalFilter: externalGlobalFilter,\n onGlobalFilterChange,\n sortingState,\n onSortingChange,\n selectable = false,\n rowSelection,\n onRowSelectionChange,\n bulkActions,\n columnToggle = false,\n exportCsv = false,\n csvFilename = \"export\",\n}: DataTableProps<T>) {\n const { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows } =\n useDataTable({\n columns,\n data,\n selectable,\n getRowId,\n pagination,\n externalGlobalFilter,\n onGlobalFilterChange,\n externalSorting: sortingState,\n onSortingChange,\n externalRowSelection: rowSelection,\n onRowSelectionChange,\n });\n\n const showToolbar = searchable || toolbar || columnToggle || exportCsv || selectedRows.length > 0;\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {showToolbar && (\n <Toolbar\n searchable={searchable}\n searchPlaceholder={searchPlaceholder}\n globalFilter={globalFilter}\n onGlobalFilterChange={handleGlobalFilterChange}\n selectedRows={selectedRows}\n bulkActions={bulkActions}\n toolbar={toolbar}\n exportCsv={exportCsv}\n columns={columns}\n data={data}\n csvFilename={csvFilename}\n columnToggle={columnToggle}\n table={table}\n />\n )}\n <Table>\n <TableHeader className=\"bg-background sticky top-0 z-10\">\n {table.getHeaderGroups().map((hg) => (\n <TableRow key={hg.id}>\n {hg.headers.map((h) => (\n <HeaderCell key={h.id} header={h} />\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n <TableBodyContent\n loading={loading}\n colSpan={tanstackColumns.length}\n emptyMessage={emptyMessage}\n rows={table.getRowModel().rows}\n onRowClick={onRowClick}\n />\n </TableBody>\n </Table>\n <PaginationFooter pagination={pagination} />\n </div>\n );\n}\nDataTable.displayName = \"DataTable\";\n\nexport { DataTable };\nexport type { SortingState, RowSelectionState, VisibilityState };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,YAAY,WAAW;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AACP,SAAS,UAAU;AACnB,SAAS,aAAa,WAAW,eAAe,YAAY,mBAAmB;AAwFvE,SAyPJ,UAzPI,KAqEA,YArEA;AAhBR,IAAM,cAAc,EAAE,MAAM,aAAa,QAAQ,eAAe,OAAO,aAAa;AAEpF,SAAS,WAAW,MAAuB;AACzC,QAAM,QAAS,MAAyC,SAAS;AACjE,SAAO,YAAY,KAAiC;AACtD;AAEA,SAAS,qBACP,SACA,YACiC;AACjC,QAAM,OAAwC,CAAC;AAC/C,MAAI,YAAY;AACd,SAAK,KAAK;AAAA,MACR,IAAI;AAAA,MACJ,QAAQ,CAAC,EAAE,MAAM,MACf;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,MAAM,yBAAyB;AAAA,UACxC,iBAAiB,CAAC,MAAM,MAAM,0BAA0B,CAAC,CAAC,CAAC;AAAA,UAC3D,cAAW;AAAA;AAAA,MACb;AAAA,MAEF,MAAM,CAAC,EAAE,IAAI,MACX;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,IAAI,cAAc;AAAA,UAC3B,iBAAiB,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,CAAC;AAAA,UAC9C,cAAW;AAAA,UACX,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA;AAAA,MACpC;AAAA,MAEF,eAAe;AAAA,MACf,cAAc;AAAA,MACd,MAAM,EAAE,OAAO,SAAS;AAAA,IAC1B,CAAC;AAAA,EACH;AACA,aAAW,OAAO,SAAS;AACzB,SAAK,KAAK;AAAA,MACR,IAAI,IAAI;AAAA,MACR,aAAa,IAAI;AAAA,MACjB,QAAQ,IAAI;AAAA,MACZ,eAAe,IAAI,YAAY;AAAA,MAC/B,cAAc,IAAI,aAAa;AAAA,MAC/B,MAAM,IAAI,SACN,CAAC,SAAS,IAAI,OAAQ,KAAK,IAAI,QAAQ,IACvC,CAAC,SAAS,OAAO,KAAK,SAAS,KAAK,EAAE;AAAA,MAC1C,MAAM,EAAE,OAAO,IAAI,MAAM;AAAA,IAC3B,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,YAAe,SAAyB,MAAW,UAAkB;AAC5E,QAAM,UAAU,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM;AAC3C,QAAM,OAAO,KAAK;AAAA,IAAI,CAAC,QACrB,QAAQ,IAAI,CAAC,QAAQ;AACnB,YAAM,MAAM,OAAO,IAAI,IAAI,GAAG,KAAK,EAAE;AACrC,aAAO,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,IAAI,IAC9D,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC,MAC3B;AAAA,IACN,CAAC;AAAA,EACH;AACA,QAAM,MAAM,CAAC,QAAQ,KAAK,GAAG,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI;AAC1E,QAAM,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAChE,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,OAAK,OAAO;AACZ,OAAK,WAAW,GAAG,QAAQ;AAC3B,OAAK,MAAM;AACX,MAAI,gBAAgB,GAAG;AACzB;AAMA,SAAS,cAAc,EAAE,UAAU,GAA0C;AAC3E,MAAI,cAAc,MAAO,QAAO,oBAAC,aAAU,WAAU,WAAU;AAC/D,MAAI,cAAc,OAAQ,QAAO,oBAAC,eAAY,WAAU,WAAU;AAClE,SAAO,oBAAC,iBAAc,WAAU,oCAAmC;AACrE;AAEA,SAAS,aAAgB,EAAE,MAAM,GAAgC;AAC/D,SACE,qBAAC,gBACC;AAAA,wBAAC,uBAAoB,SAAO,MAC1B,+BAAC,UAAO,SAAQ,WAAU,MAAK,MAC7B;AAAA,0BAAC,eAAY,WAAU,gBAAe;AAAA,MAAE;AAAA,OAE1C,GACF;AAAA,IACA,qBAAC,uBAAoB,OAAM,OACzB;AAAA,0BAAC,qBAAkB,4BAAc;AAAA,MACjC,oBAAC,yBAAsB;AAAA,MACtB,MACE,cAAc,EACd,OAAO,CAAC,QAAQ,IAAI,WAAW,CAAC,EAChC,IAAI,CAAC,QACJ;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,IAAI,aAAa;AAAA,UAC1B,iBAAiB,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC;AAAA,UAE/C,cAAI,UAAU;AAAA;AAAA,QAJV,IAAI;AAAA,MAKX,CACD;AAAA,OACL;AAAA,KACF;AAEJ;AAEA,SAAS,WAAc,EAAE,OAAO,GAAmC;AACjE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT,WAAW,OAAO,OAAO,UAAU,IAAI;AAAA,QACvC,OAAO,OAAO,WAAW,KAAK;AAAA,MAChC;AAAA,MACA,SAAS,OAAO,OAAO,wBAAwB;AAAA,MAE/C,+BAAC,UAAK,WAAU,kCACb;AAAA,mBAAW,OAAO,OAAO,UAAU,QAAQ,OAAO,WAAW,CAAC;AAAA,QAC9D,OAAO,OAAO,WAAW,KAAK,oBAAC,iBAAc,WAAW,OAAO,OAAO,YAAY,GAAG;AAAA,SACxF;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,SAAY,EAAE,KAAK,GAA+B;AACzD,SACE,oBAAC,aAAU,WAAW,WAAW,KAAK,OAAO,UAAU,IAAI,GACxD,qBAAW,KAAK,OAAO,UAAU,MAAM,KAAK,WAAW,CAAC,GAC3D;AAEJ;AAEA,SAAS,QAAW,EAAE,KAAK,WAAW,GAAiD;AACrF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY,IAAI,cAAc,IAAI,aAAa;AAAA,MAC/C,WAAW,GAAG,cAAc,gBAAgB;AAAA,MAC5C,SAAS,aAAa,MAAM,WAAW,IAAI,QAAQ,IAAI;AAAA,MAEtD,cAAI,gBAAgB,EAAE,IAAI,CAAC,SAC1B,oBAAC,YAAuB,QAAT,KAAK,EAAgB,CACrC;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,aAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,qBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,MAAM,YAAY,SAAS,MAAM,WAAW,GACvF;AAAA,wBAAC,cAAW,WAAU,gBAAe;AAAA,IAAE;AAAA,KAEzC;AAEJ;AAEA,SAAS,eAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AACD,SACE,qBAAC,SAAI,WAAU,2BACb;AAAA,yBAAC,UAAK,WAAU,iCAAiC;AAAA,mBAAa;AAAA,MAAO;AAAA,OAAS;AAAA,IAC7E,YAAY,YAAY;AAAA,KAC3B;AAEJ;AAEA,SAAS,QAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAcG;AACD,QAAM,eAAe,aAAa,SAAS;AAC3C,SACE,qBAAC,SAAI,WAAU,2BACZ;AAAA,kBACC;AAAA,MAAC;AAAA;AAAA,QACC,aAAa;AAAA,QACb,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,qBAAqB,EAAE,OAAO,KAAK;AAAA,QACpD,WAAU;AAAA;AAAA,IACZ;AAAA,IAED,gBAAgB,eACf,oBAAC,kBAAe,cAA4B,aAA0B;AAAA,IAExE,qBAAC,SAAI,WAAU,mCACZ;AAAA;AAAA,MACA,aAAa,oBAAC,gBAAa,SAAkB,MAAY,aAA0B;AAAA,MACnF,gBAAgB,oBAAC,gBAAa,OAAc;AAAA,OAC/C;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,MAAI,SAAS;AACX,WACE,oBAAC,YACC,8BAAC,aAAU,SAAkB,WAAU,oBACrC,8BAAC,WAAQ,MAAK,MAAK,WAAU,WAAU,GACzC,GACF;AAAA,EAEJ;AACA,MAAI,KAAK,WAAW,GAAG;AACrB,WACE,oBAAC,YACC,8BAAC,aAAU,SAAkB,WAAU,oBACpC,wBACH,GACF;AAAA,EAEJ;AACA,SACE,gCACG,eAAK,IAAI,CAAC,QACT,oBAAC,WAAqB,KAAU,cAAlB,IAAI,EAAsC,CACzD,GACH;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,qBAAC,SAAI,WAAU,2BACb;AAAA,wBAAC,UAAK,WAAU,iCAAgC,2BAAa;AAAA,IAC7D,qBAAC,UAAO,OAAO,OAAO,QAAQ,GAAG,eAAe,CAAC,MAAM,SAAS,OAAO,CAAC,CAAC,GACvE;AAAA,0BAAC,iBAAc,WAAU,gBACvB,8BAAC,eAAY,GACf;AAAA,MACA,oBAAC,iBACE,kBAAQ,IAAI,CAAC,SACZ,oBAAC,cAAsB,OAAO,OAAO,IAAI,GACtC,kBADc,IAEjB,CACD,GACH;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAiB,EAAE,WAAW,GAAyC;AAC9E,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,eACJ,WAAW,mBAAmB,WAAW,aAAa,UAAa,WAAW;AAChF,QAAM,YAAY,WAAW,aAAa;AAC1C,MAAI,CAAC,gBAAgB,CAAC,UAAW,QAAO;AACxC,SACE,qBAAC,SAAI,WAAU,qCACZ;AAAA,mBACC;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,WAAW;AAAA,QACrB,SAAS,WAAW;AAAA,QACpB,UAAU,WAAW;AAAA;AAAA,IACvB,IAEA,oBAAC,SAAI;AAAA,IAEN,aACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,WAAW;AAAA,QACjB,YAAY,WAAW;AAAA,QACvB,SAAS,WAAW;AAAA,QACpB,cAAc,WAAW;AAAA;AAAA,IAC3B;AAAA,KAEJ;AAEJ;AAoBA,SAAS,aAAgB,MAA8B;AACrD,QAAM,oBAAoB,KAAK,yBAAyB;AACxD,QAAM,kBAAkB,KAAK,oBAAoB;AAEjD,QAAM,CAAC,iBAAiB,kBAAkB,IAAU,eAAuB,CAAC,CAAC;AAC7E,QAAM,CAAC,sBAAsB,uBAAuB,IAAU,eAAS,EAAE;AACzE,QAAM,CAAC,sBAAsB,uBAAuB,IAAU,eAA4B,CAAC,CAAC;AAC5F,QAAM,CAAC,kBAAkB,mBAAmB,IAAU,eAA0B,CAAC,CAAC;AAElF,QAAM,UAAU,KAAK,mBAAmB;AACxC,QAAM,eAAe,KAAK,wBAAwB;AAClD,QAAM,oBAAoB,KAAK,wBAAwB;AAEvD,QAAM,sBAAsB,KAAK,kBAC7B,CAAC,YAAmE;AAClE,SAAK,gBAAkB,QAAiD,OAAO,CAAC;AAAA,EAClF,IACA;AAEJ,QAAM,2BAA2B,KAAK,wBAAwB;AAE9D,QAAM,2BAA2B,KAAK,uBAClC,CAAC,YAAkF;AACjF,SAAK;AAAA,MACF,QAA2D,iBAAiB;AAAA,IAC/E;AAAA,EACF,IACA;AAEJ,QAAM,kBAAwB;AAAA,IAC5B,MAAM,qBAAqB,KAAK,SAAS,KAAK,UAAU;AAAA,IACxD,CAAC,KAAK,SAAS,KAAK,UAAU;AAAA,EAChC;AAEA,QAAM,QAAQ,cAAc;AAAA,IAC1B,MAAM,KAAK;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,MACL;AAAA,MACA,cAAc,oBAAoB,SAAY;AAAA,MAC9C,cAAc;AAAA,MACd;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,IACjB,sBAAsB,oBAAoB,SAAY;AAAA,IACtD,sBAAsB;AAAA,IACtB,0BAA0B;AAAA,IAC1B,iBAAiB,gBAAgB;AAAA,IACjC,mBAAmB,kBAAkB,SAAY,kBAAkB;AAAA,IACnE,qBAAqB,oBAAoB,SAAY,oBAAoB;AAAA,IACzE,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,kBAAkB,KAAK,eAAe;AAAA,IACtC,oBAAoB,KAAK;AAAA,IACzB,UAAU,KAAK,WAAW,CAAC,QAAQ,KAAK,SAAU,GAAG,IAAI;AAAA,EAC3D,CAAC;AAED,QAAM,eAAe,KAAK,aACtB,MAAM,oBAAoB,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,IACtD,CAAC;AAEL,SAAO,EAAE,OAAO,iBAAiB,cAAc,0BAA0B,aAAa;AACxF;AAMA,SAAS,UAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB;AAAA,EACA,UAAU;AAAA,EACV,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAChB,GAAsB;AACpB,QAAM,EAAE,OAAO,iBAAiB,cAAc,0BAA0B,aAAa,IACnF,aAAa;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,EACF,CAAC;AAEH,QAAM,cAAc,cAAc,WAAW,gBAAgB,aAAa,aAAa,SAAS;AAEhG,SACE,qBAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC;AAAA,mBACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAEF,qBAAC,SACC;AAAA,0BAAC,eAAY,WAAU,mCACpB,gBAAM,gBAAgB,EAAE,IAAI,CAAC,OAC5B,oBAAC,YACE,aAAG,QAAQ,IAAI,CAAC,MACf,oBAAC,cAAsB,QAAQ,KAAd,EAAE,EAAe,CACnC,KAHY,GAAG,EAIlB,CACD,GACH;AAAA,MACA,oBAAC,aACC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,SAAS,gBAAgB;AAAA,UACzB;AAAA,UACA,MAAM,MAAM,YAAY,EAAE;AAAA,UAC1B;AAAA;AAAA,MACF,GACF;AAAA,OACF;AAAA,IACA,oBAAC,oBAAiB,YAAwB;AAAA,KAC5C;AAEJ;AACA,UAAU,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["/** Feature-complete admin data table built on TanStack Table. */\n\"use client\";\n\nimport * as React from \"react\";\nimport {\n flexRender,\n functionalUpdate,\n getCoreRowModel,\n getSortedRowModel,\n getFilteredRowModel,\n useReactTable,\n type ColumnDef as TanstackColumnDef,\n type SortingState,\n type RowSelectionState,\n type Updater,\n type VisibilityState,\n type Table as TanstackTable,\n type Header,\n type Row,\n type Cell,\n} from \"@tanstack/react-table\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { LuArrowDown, LuArrowUp, LuArrowUpDown, LuDownload, LuSettings2 } from \"react-icons/lu\";\nimport { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"./table\";\nimport { Input } from \"./input\";\nimport { Spinner } from \"./spinner\";\nimport { Checkbox } from \"./checkbox\";\nimport { Button } from \"./button\";\nimport { ListPagination } from \"./pagination\";\nimport { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from \"./select\";\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuCheckboxItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n} from \"./dropdown-menu\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ColumnDef<T> {\n key: keyof T & string;\n header: string;\n sortable?: boolean;\n render?: (row: T) => React.ReactNode;\n align?: \"left\" | \"center\" | \"right\";\n hideable?: boolean;\n}\n\nexport interface DataTablePagination {\n page: number;\n totalPages: number;\n getHref: (page: number) => string;\n onPageChange?: (page: number) => void;\n /** Current page size. Required when pageSizeOptions is set. */\n pageSize?: number;\n /** Available page size options. Renders a dropdown when provided. */\n pageSizeOptions?: number[];\n /** Called when the user selects a different page size. */\n onPageSizeChange?: (size: number) => void;\n}\n\nexport interface DataTableProps<T> {\n columns: ColumnDef<T>[];\n data: T[];\n searchable?: boolean;\n searchPlaceholder?: string;\n onRowClick?: (row: T) => void;\n loading?: boolean;\n emptyMessage?: string;\n toolbar?: React.ReactNode;\n className?: string;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n globalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n sortingState?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n selectable?: boolean;\n rowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n bulkActions?: (selectedRows: T[]) => React.ReactNode;\n columnToggle?: boolean;\n exportCsv?: boolean;\n csvFilename?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst ALIGN_CLASS = { left: \"text-left\", center: \"text-center\", right: \"text-right\" } as const;\n\nfunction getAlignCn(meta: unknown): string {\n const align = (meta as { align?: string } | undefined)?.align ?? \"left\";\n return ALIGN_CLASS[align as keyof typeof ALIGN_CLASS];\n}\n\nfunction buildTanstackColumns<T>(\n columns: ColumnDef<T>[],\n selectable: boolean,\n): TanstackColumnDef<T, unknown>[] {\n const cols: TanstackColumnDef<T, unknown>[] = [];\n if (selectable) {\n cols.push({\n id: \"_select\",\n header: ({ table }) => (\n <Checkbox\n checked={table.getIsAllPageRowsSelected()}\n onCheckedChange={(v) => table.toggleAllPageRowsSelected(!!v)}\n aria-label=\"Select all\"\n />\n ),\n cell: ({ row }) => (\n <Checkbox\n checked={row.getIsSelected()}\n onCheckedChange={(v) => row.toggleSelected(!!v)}\n aria-label=\"Select row\"\n onClick={(e) => e.stopPropagation()}\n />\n ),\n enableSorting: false,\n enableHiding: false,\n meta: { align: \"center\" },\n });\n }\n for (const col of columns) {\n cols.push({\n id: col.key,\n accessorKey: col.key,\n header: col.header,\n enableSorting: col.sortable ?? false,\n enableHiding: col.hideable !== false,\n cell: col.render\n ? (info) => col.render!(info.row.original)\n : (info) => String(info.getValue() ?? \"\"),\n meta: { align: col.align },\n });\n }\n return cols;\n}\n\nfunction exportToCsv<T>(columns: ColumnDef<T>[], data: T[], filename: string) {\n const headers = columns.map((c) => c.header);\n const rows = data.map((row) =>\n columns.map((col) => {\n const str = String(row[col.key] ?? \"\");\n return str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")\n ? `\"${str.replace(/\"/g, '\"\"')}\"`\n : str;\n }),\n );\n const csv = [headers.join(\",\"), ...rows.map((r) => r.join(\",\"))].join(\"\\n\");\n const blob = new Blob([csv], { type: \"text/csv;charset=utf-8;\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = `${filename}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction SortIndicator({ direction }: { direction: false | \"asc\" | \"desc\" }) {\n if (direction === \"asc\") return <LuArrowUp className=\"h-4 w-4\" />;\n if (direction === \"desc\") return <LuArrowDown className=\"h-4 w-4\" />;\n return <LuArrowUpDown className=\"text-muted-foreground/50 h-4 w-4\" />;\n}\n\nfunction ColumnToggle<T>({ table }: { table: TanstackTable<T> }) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <LuSettings2 className=\"mr-2 h-4 w-4\" />\n Columns\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {table\n .getAllColumns()\n .filter((col) => col.getCanHide())\n .map((col) => (\n <DropdownMenuCheckboxItem\n key={col.id}\n checked={col.getIsVisible()}\n onCheckedChange={(v) => col.toggleVisibility(!!v)}\n >\n {col.columnDef.header as string}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nfunction HeaderCell<T>({ header }: { header: Header<T, unknown> }) {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n // aria-sort announces sort state to screen readers; only meaningful on\n // sortable columns. Sorting is triggered by a real <button> so it is\n // keyboard-focusable and Enter/Space-activatable (a click handler on the\n // <th> alone is mouse-only).\n const ariaSort = canSort\n ? sorted === \"asc\"\n ? \"ascending\"\n : sorted === \"desc\"\n ? \"descending\"\n : \"none\"\n : undefined;\n\n return (\n <TableHead className={getAlignCn(header.column.columnDef.meta)} aria-sort={ariaSort}>\n {canSort ? (\n <button\n type=\"button\"\n onClick={header.column.getToggleSortingHandler()}\n className=\"inline-flex cursor-pointer select-none items-center gap-1\"\n >\n {flexRender(header.column.columnDef.header, header.getContext())}\n <SortIndicator direction={sorted} />\n </button>\n ) : (\n <span className=\"inline-flex items-center gap-1\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n </span>\n )}\n </TableHead>\n );\n}\n\nfunction DataCell<T>({ cell }: { cell: Cell<T, unknown> }) {\n return (\n <TableCell className={getAlignCn(cell.column.columnDef.meta)}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n );\n}\n\nfunction DataRow<T>({ row, onRowClick }: { row: Row<T>; onRowClick?: (r: T) => void }) {\n return (\n <TableRow\n data-state={row.getIsSelected() ? \"selected\" : undefined}\n className={cn(onRowClick && \"cursor-pointer\")}\n onClick={onRowClick ? () => onRowClick(row.original) : undefined}\n >\n {row.getVisibleCells().map((cell) => (\n <DataCell key={cell.id} cell={cell} />\n ))}\n </TableRow>\n );\n}\n\nfunction ExportButton<T>({\n columns,\n data,\n csvFilename,\n}: {\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n}) {\n return (\n <Button variant=\"outline\" size=\"sm\" onClick={() => exportToCsv(columns, data, csvFilename)}>\n <LuDownload className=\"mr-2 h-4 w-4\" />\n Export\n </Button>\n );\n}\n\nfunction BulkActionsBar<T>({\n selectedRows,\n bulkActions,\n}: {\n selectedRows: T[];\n bulkActions: (rows: T[]) => React.ReactNode;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">{selectedRows.length} selected</span>\n {bulkActions(selectedRows)}\n </div>\n );\n}\n\nfunction Toolbar<T>({\n searchable,\n searchPlaceholder,\n globalFilter,\n onGlobalFilterChange,\n selectedRows,\n bulkActions,\n toolbar,\n exportCsv,\n columns,\n data,\n csvFilename,\n columnToggle,\n table,\n}: {\n searchable: boolean;\n searchPlaceholder: string;\n globalFilter: string;\n onGlobalFilterChange: (value: string) => void;\n selectedRows: T[];\n bulkActions?: (rows: T[]) => React.ReactNode;\n toolbar?: React.ReactNode;\n exportCsv: boolean;\n columns: ColumnDef<T>[];\n data: T[];\n csvFilename: string;\n columnToggle: boolean;\n table: TanstackTable<T>;\n}) {\n const hasSelection = selectedRows.length > 0;\n return (\n <div className=\"flex items-center gap-4\">\n {searchable && (\n <Input\n placeholder={searchPlaceholder}\n value={globalFilter}\n onChange={(e) => onGlobalFilterChange(e.target.value)}\n className=\"max-w-sm\"\n />\n )}\n {hasSelection && bulkActions && (\n <BulkActionsBar selectedRows={selectedRows} bulkActions={bulkActions} />\n )}\n <div className=\"ml-auto flex items-center gap-2\">\n {toolbar}\n {exportCsv && <ExportButton columns={columns} data={data} csvFilename={csvFilename} />}\n {columnToggle && <ColumnToggle table={table} />}\n </div>\n </div>\n );\n}\n\nfunction TableBodyContent<T>({\n loading,\n colSpan,\n emptyMessage,\n rows,\n onRowClick,\n}: {\n loading: boolean;\n colSpan: number;\n emptyMessage: string;\n rows: Row<T>[];\n onRowClick?: (r: T) => void;\n}) {\n if (loading) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n <Spinner size=\"lg\" className=\"mx-auto\" />\n </TableCell>\n </TableRow>\n );\n }\n if (rows.length === 0) {\n return (\n <TableRow>\n <TableCell colSpan={colSpan} className=\"h-24 text-center\">\n {emptyMessage}\n </TableCell>\n </TableRow>\n );\n }\n return (\n <>\n {rows.map((row) => (\n <DataRow key={row.id} row={row} onRowClick={onRowClick} />\n ))}\n </>\n );\n}\n\nfunction PageSizeSelector({\n pageSize,\n options,\n onChange,\n}: {\n pageSize: number;\n options: number[];\n onChange: (size: number) => void;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-muted-foreground text-sm\">Rows per page</span>\n <Select value={String(pageSize)} onValueChange={(v) => onChange(Number(v))}>\n <SelectTrigger className=\"h-8 w-[70px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {options.map((size) => (\n <SelectItem key={size} value={String(size)}>\n {size}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n}\n\nfunction PaginationFooter({ pagination }: { pagination?: DataTablePagination }) {\n if (!pagination) return null;\n const showPageSize =\n pagination.pageSizeOptions && pagination.pageSize !== undefined && pagination.onPageSizeChange;\n const showPages = pagination.totalPages > 1;\n if (!showPageSize && !showPages) return null;\n return (\n <div className=\"flex items-center justify-between\">\n {showPageSize ? (\n <PageSizeSelector\n pageSize={pagination.pageSize!}\n options={pagination.pageSizeOptions!}\n onChange={pagination.onPageSizeChange!}\n />\n ) : (\n <div />\n )}\n {showPages && (\n <ListPagination\n page={pagination.page}\n totalPages={pagination.totalPages}\n getHref={pagination.getHref}\n onPageChange={pagination.onPageChange}\n />\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Hook: encapsulates all state management and TanStack Table configuration\n// ---------------------------------------------------------------------------\n\ninterface UseDataTableOptions<T> {\n columns: ColumnDef<T>[];\n data: T[];\n selectable: boolean;\n getRowId?: (row: T) => string;\n pagination?: DataTablePagination;\n externalGlobalFilter?: string;\n onGlobalFilterChange?: (value: string) => void;\n externalSorting?: SortingState;\n onSortingChange?: (state: SortingState) => void;\n externalRowSelection?: RowSelectionState;\n onRowSelectionChange?: (state: RowSelectionState) => void;\n}\n\nfunction useDataTable<T>(opts: UseDataTableOptions<T>) {\n const isManualFiltering = opts.externalGlobalFilter !== undefined;\n const isManualSorting = opts.externalSorting !== undefined;\n\n const [internalSorting, setInternalSorting] = React.useState<SortingState>([]);\n const [internalGlobalFilter, setInternalGlobalFilter] = React.useState(\"\");\n const [internalRowSelection, setInternalRowSelection] = React.useState<RowSelectionState>({});\n const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});\n\n const sorting = opts.externalSorting ?? internalSorting;\n const globalFilter = opts.externalGlobalFilter ?? internalGlobalFilter;\n const rowSelectionState = opts.externalRowSelection ?? internalRowSelection;\n\n // TanStack hands these an Updater<T> = T | ((old: T) => T). Resolve via\n // functionalUpdate so a plain value (e.g. from resetRowSelection()/setSorting(v))\n // is not called as a function — the old cast-and-call threw on plain values.\n const handleSortingChange = opts.onSortingChange\n ? (updater: Updater<SortingState>) => {\n opts.onSortingChange!(functionalUpdate(updater, sorting));\n }\n : setInternalSorting;\n\n const handleGlobalFilterChange = opts.onGlobalFilterChange ?? setInternalGlobalFilter;\n\n const handleRowSelectionChange = opts.onRowSelectionChange\n ? (updater: Updater<RowSelectionState>) => {\n opts.onRowSelectionChange!(functionalUpdate(updater, rowSelectionState));\n }\n : setInternalRowSelection;\n\n const tanstackColumns = React.useMemo(\n () => buildTanstackColumns(opts.columns, opts.selectable),\n [opts.columns, opts.selectable],\n );\n\n const table = useReactTable({\n data: opts.data,\n columns: tanstackColumns,\n state: {\n sorting,\n globalFilter: isManualFiltering ? undefined : globalFilter,\n rowSelection: rowSelectionState,\n columnVisibility,\n },\n onSortingChange: handleSortingChange,\n onGlobalFilterChange: isManualFiltering ? undefined : setInternalGlobalFilter,\n onRowSelectionChange: handleRowSelectionChange,\n onColumnVisibilityChange: setColumnVisibility,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: isManualSorting ? undefined : getSortedRowModel(),\n getFilteredRowModel: isManualFiltering ? undefined : getFilteredRowModel(),\n manualSorting: isManualSorting,\n manualFiltering: isManualFiltering,\n manualPagination: opts.pagination !== undefined,\n enableRowSelection: opts.selectable,\n getRowId: opts.getRowId ? (row) => opts.getRowId!(row) : undefined,\n });\n\n const selectedRows = opts.selectable\n ? table.getSelectedRowModel().rows.map((r) => r.original)\n : [];\n\n return { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows };\n}\n\n// ---------------------------------------------------------------------------\n// Main component\n// ---------------------------------------------------------------------------\n\nfunction DataTable<T>({\n columns,\n data,\n searchable = false,\n searchPlaceholder = \"Search...\",\n onRowClick,\n loading = false,\n emptyMessage = \"No results.\",\n toolbar,\n className,\n getRowId,\n pagination,\n globalFilter: externalGlobalFilter,\n onGlobalFilterChange,\n sortingState,\n onSortingChange,\n selectable = false,\n rowSelection,\n onRowSelectionChange,\n bulkActions,\n columnToggle = false,\n exportCsv = false,\n csvFilename = \"export\",\n}: DataTableProps<T>) {\n const { table, tanstackColumns, globalFilter, handleGlobalFilterChange, selectedRows } =\n useDataTable({\n columns,\n data,\n selectable,\n getRowId,\n pagination,\n externalGlobalFilter,\n onGlobalFilterChange,\n externalSorting: sortingState,\n onSortingChange,\n externalRowSelection: rowSelection,\n onRowSelectionChange,\n });\n\n const showToolbar = searchable || toolbar || columnToggle || exportCsv || selectedRows.length > 0;\n\n return (\n <div className={cn(\"space-y-4\", className)}>\n {showToolbar && (\n <Toolbar\n searchable={searchable}\n searchPlaceholder={searchPlaceholder}\n globalFilter={globalFilter}\n onGlobalFilterChange={handleGlobalFilterChange}\n selectedRows={selectedRows}\n bulkActions={bulkActions}\n toolbar={toolbar}\n exportCsv={exportCsv}\n columns={columns}\n data={data}\n csvFilename={csvFilename}\n columnToggle={columnToggle}\n table={table}\n />\n )}\n <Table>\n <TableHeader className=\"bg-background sticky top-0 z-10\">\n {table.getHeaderGroups().map((hg) => (\n <TableRow key={hg.id}>\n {hg.headers.map((h) => (\n <HeaderCell key={h.id} header={h} />\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>\n <TableBodyContent\n loading={loading}\n colSpan={tanstackColumns.length}\n emptyMessage={emptyMessage}\n rows={table.getRowModel().rows}\n onRowClick={onRowClick}\n />\n </TableBody>\n </Table>\n <PaginationFooter pagination={pagination} />\n </div>\n );\n}\nDataTable.displayName = \"DataTable\";\n\nexport { DataTable };\nexport type { SortingState, RowSelectionState, VisibilityState };\n"],"mappings":"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","names":[]}
@@ -2,14 +2,14 @@
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunkWJUDOEVBcjs = require('./chunk-WJUDOEVB.cjs');
6
-
7
-
8
5
  var _chunkZ57QBVUCcjs = require('./chunk-Z57QBVUC.cjs');
9
6
  require('./chunk-5ZITWMV4.cjs');
10
7
 
11
8
 
12
9
  var _chunk32XB3REYcjs = require('./chunk-32XB3REY.cjs');
10
+
11
+
12
+ var _chunkWJUDOEVBcjs = require('./chunk-WJUDOEVB.cjs');
13
13
  require('./chunk-BXMTQGKV.cjs');
14
14
  require('./chunk-76RSVRGB.cjs');
15
15
  require('./chunk-7EXXNELX.cjs');
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/detail-panel.cjs","../src/detail-panel.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/detail-panel.cjs","sourcesContent":[null,"/** Read/edit toggle panel for a single record. */\n\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { Button } from \"./button\";\nimport { FormInput } from \"./form-input\";\nimport { FormSelect } from \"./form-select\";\nimport { FormTextarea } from \"./form-textarea\";\nimport { Spinner } from \"./spinner\";\n\nexport interface FieldDef<T> {\n /** Property key on the data object. */\n key: keyof T & string;\n /** Display label. */\n label: string;\n /** Field type determines the input component used in edit mode. */\n type: \"text\" | \"textarea\" | \"select\" | \"readonly\";\n /** Options for select fields. */\n options?: { label: string; value: string }[];\n /** Mark the field as required in edit mode. */\n required?: boolean;\n /** Custom read-mode renderer. Receives the field value. */\n render?: (value: T[keyof T]) => React.ReactNode;\n}\n\nexport interface DetailPanelProps<T extends object> {\n /** Field definitions describing each field. */\n fields: FieldDef<T>[];\n /** The record to display/edit. */\n data: T;\n /** Called with the updated record when the user saves. */\n onSave: (data: T) => void;\n /** Called when the user cancels editing. */\n onCancel?: () => void;\n /** Whether a save operation is in progress. */\n loading?: boolean;\n /** Optional title displayed above the fields. */\n title?: string;\n /** Additional class name for the root container. */\n className?: string;\n /** Start in edit mode. */\n defaultEditing?: boolean;\n}\n\n/**\n * Read/edit toggle panel for a single record. Renders field values in read\n * mode, and form inputs in edit mode based on field definitions.\n *\n * @example\n * ```tsx\n * const fields: FieldDef<Brand>[] = [\n * { key: \"brandsName\", label: \"Name\", type: \"text\", required: true },\n * { key: \"brandsDesc\", label: \"Description\", type: \"textarea\" },\n * { key: \"brandsUid\", label: \"UID\", type: \"readonly\" },\n * ];\n *\n * <DetailPanel fields={fields} data={brand} onSave={handleSave} />\n * ```\n */\nfunction DetailPanel<T extends object>({\n fields,\n data,\n onSave,\n onCancel,\n loading = false,\n title,\n className,\n defaultEditing = false,\n}: DetailPanelProps<T>) {\n const [editing, setEditing] = React.useState(defaultEditing);\n const [draft, setDraft] = React.useState<T>(data);\n\n React.useEffect(() => {\n setDraft(data);\n }, [data]);\n\n const handleEdit = () => {\n setDraft(data);\n setEditing(true);\n };\n\n const handleCancel = () => {\n setDraft(data);\n setEditing(false);\n onCancel?.();\n };\n\n const handleSave = () => {\n onSave(draft);\n };\n\n const updateField = (key: keyof T & string, value: unknown) => {\n setDraft((prev) => ({ ...prev, [key]: value }));\n };\n\n return (\n <div className={cn(\"space-y-6\", className)}>\n {(title || !editing) && (\n <div className=\"flex items-center justify-between\">\n {title && <h3 className=\"text-lg font-semibold\">{title}</h3>}\n {!editing && (\n <Button variant=\"outline\" size=\"sm\" onClick={handleEdit}>\n Edit\n </Button>\n )}\n </div>\n )}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {fields.map((field) =>\n editing ? (\n <EditField\n key={field.key}\n field={field}\n value={draft[field.key]}\n onChange={updateField}\n />\n ) : (\n <ReadField key={field.key} field={field} value={data[field.key]} />\n ),\n )}\n </div>\n {editing && (\n <div className=\"flex gap-2\">\n <Button onClick={handleSave} disabled={loading}>\n {loading && <Spinner size=\"sm\" className=\"mr-2\" />}\n Save\n </Button>\n <Button variant=\"outline\" onClick={handleCancel} disabled={loading}>\n Cancel\n </Button>\n </div>\n )}\n </div>\n );\n}\nDetailPanel.displayName = \"DetailPanel\";\n\nfunction ReadField<T>({ field, value }: { field: FieldDef<T>; value: T[keyof T] }) {\n const display = field.render ? field.render(value) : String(value ?? \"\");\n return (\n <div className=\"space-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{field.label}</p>\n <p className=\"text-sm\">{display}</p>\n </div>\n );\n}\n\nfunction EditField<T>({\n field,\n value,\n onChange,\n}: {\n field: FieldDef<T>;\n value: unknown;\n onChange: (key: keyof T & string, value: unknown) => void;\n}) {\n const strValue = String(value ?? \"\");\n\n if (field.type === \"readonly\") {\n return (\n <div className=\"space-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{field.label}</p>\n <p className=\"text-sm\">{field.render ? field.render(value as T[keyof T]) : strValue}</p>\n </div>\n );\n }\n\n if (field.type === \"select\") {\n return (\n <FormSelect\n label={field.label}\n name={field.key}\n required={field.required}\n options={field.options ?? []}\n value={strValue}\n onValueChange={(v) => onChange(field.key, v)}\n />\n );\n }\n\n if (field.type === \"textarea\") {\n return (\n <FormTextarea\n label={field.label}\n name={field.key}\n required={field.required}\n value={strValue}\n onChange={(e) => onChange(field.key, e.target.value)}\n />\n );\n }\n\n return (\n <FormInput\n label={field.label}\n name={field.key}\n required={field.required}\n value={strValue}\n onChange={(e) => onChange(field.key, e.target.value)}\n />\n );\n}\n\nexport { DetailPanel };\n"]}
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/detail-panel.cjs","../src/detail-panel.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/detail-panel.cjs","sourcesContent":[null,"/** Read/edit toggle panel for a single record. */\n\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { Button } from \"./button\";\nimport { FormInput } from \"./form-input\";\nimport { FormSelect } from \"./form-select\";\nimport { FormTextarea } from \"./form-textarea\";\nimport { Spinner } from \"./spinner\";\n\nexport interface FieldDef<T> {\n /** Property key on the data object. */\n key: keyof T & string;\n /** Display label. */\n label: string;\n /** Field type determines the input component used in edit mode. */\n type: \"text\" | \"textarea\" | \"select\" | \"readonly\";\n /** Options for select fields. */\n options?: { label: string; value: string }[];\n /** Mark the field as required in edit mode. */\n required?: boolean;\n /** Custom read-mode renderer. Receives the field value. */\n render?: (value: T[keyof T]) => React.ReactNode;\n}\n\nexport interface DetailPanelProps<T extends object> {\n /** Field definitions describing each field. */\n fields: FieldDef<T>[];\n /** The record to display/edit. */\n data: T;\n /** Called with the updated record when the user saves. */\n onSave: (data: T) => void;\n /** Called when the user cancels editing. */\n onCancel?: () => void;\n /** Whether a save operation is in progress. */\n loading?: boolean;\n /** Optional title displayed above the fields. */\n title?: string;\n /** Additional class name for the root container. */\n className?: string;\n /** Start in edit mode. */\n defaultEditing?: boolean;\n}\n\n/**\n * Read/edit toggle panel for a single record. Renders field values in read\n * mode, and form inputs in edit mode based on field definitions.\n *\n * @example\n * ```tsx\n * const fields: FieldDef<Brand>[] = [\n * { key: \"brandsName\", label: \"Name\", type: \"text\", required: true },\n * { key: \"brandsDesc\", label: \"Description\", type: \"textarea\" },\n * { key: \"brandsUid\", label: \"UID\", type: \"readonly\" },\n * ];\n *\n * <DetailPanel fields={fields} data={brand} onSave={handleSave} />\n * ```\n */\nfunction DetailPanel<T extends object>({\n fields,\n data,\n onSave,\n onCancel,\n loading = false,\n title,\n className,\n defaultEditing = false,\n}: DetailPanelProps<T>) {\n const [editing, setEditing] = React.useState(defaultEditing);\n const [draft, setDraft] = React.useState<T>(data);\n\n React.useEffect(() => {\n setDraft(data);\n }, [data]);\n\n const handleEdit = () => {\n setDraft(data);\n setEditing(true);\n };\n\n const handleCancel = () => {\n setDraft(data);\n setEditing(false);\n onCancel?.();\n };\n\n const handleSave = () => {\n onSave(draft);\n };\n\n const updateField = (key: keyof T & string, value: unknown) => {\n setDraft((prev) => ({ ...prev, [key]: value }));\n };\n\n return (\n <div className={cn(\"space-y-6\", className)}>\n {(title || !editing) && (\n <div className=\"flex items-center justify-between\">\n {title && <h3 className=\"text-lg font-semibold\">{title}</h3>}\n {!editing && (\n <Button variant=\"outline\" size=\"sm\" onClick={handleEdit}>\n Edit\n </Button>\n )}\n </div>\n )}\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {fields.map((field) =>\n editing ? (\n <EditField\n key={field.key}\n field={field}\n value={draft[field.key]}\n onChange={updateField}\n />\n ) : (\n <ReadField key={field.key} field={field} value={data[field.key]} />\n ),\n )}\n </div>\n {editing && (\n <div className=\"flex gap-2\">\n <Button onClick={handleSave} disabled={loading}>\n {loading && <Spinner size=\"sm\" className=\"mr-2\" />}\n Save\n </Button>\n <Button variant=\"outline\" onClick={handleCancel} disabled={loading}>\n Cancel\n </Button>\n </div>\n )}\n </div>\n );\n}\nDetailPanel.displayName = \"DetailPanel\";\n\nfunction ReadField<T>({ field, value }: { field: FieldDef<T>; value: T[keyof T] }) {\n const display = field.render ? field.render(value) : String(value ?? \"\");\n return (\n <div className=\"space-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{field.label}</p>\n <p className=\"text-sm\">{display}</p>\n </div>\n );\n}\n\nfunction EditField<T>({\n field,\n value,\n onChange,\n}: {\n field: FieldDef<T>;\n value: unknown;\n onChange: (key: keyof T & string, value: unknown) => void;\n}) {\n const strValue = String(value ?? \"\");\n\n if (field.type === \"readonly\") {\n return (\n <div className=\"space-y-1\">\n <p className=\"text-muted-foreground text-sm font-medium\">{field.label}</p>\n <p className=\"text-sm\">{field.render ? field.render(value as T[keyof T]) : strValue}</p>\n </div>\n );\n }\n\n if (field.type === \"select\") {\n return (\n <FormSelect\n label={field.label}\n name={field.key}\n required={field.required}\n options={field.options ?? []}\n value={strValue}\n onValueChange={(v) => onChange(field.key, v)}\n />\n );\n }\n\n if (field.type === \"textarea\") {\n return (\n <FormTextarea\n label={field.label}\n name={field.key}\n required={field.required}\n value={strValue}\n onChange={(e) => onChange(field.key, e.target.value)}\n />\n );\n }\n\n return (\n <FormInput\n label={field.label}\n name={field.key}\n required={field.required}\n value={strValue}\n onChange={(e) => onChange(field.key, e.target.value)}\n />\n );\n}\n\nexport { DetailPanel };\n"]}
@@ -1,8 +1,5 @@
1
1
  "use client";
2
2
  "use client";
3
- import {
4
- FormSelect
5
- } from "./chunk-WFMP6TZN.js";
6
3
  import {
7
4
  FormTextarea
8
5
  } from "./chunk-RGJT67PN.js";
@@ -10,6 +7,9 @@ import "./chunk-L3BT67EO.js";
10
7
  import {
11
8
  FormInput
12
9
  } from "./chunk-UB7HYAAC.js";
10
+ import {
11
+ FormSelect
12
+ } from "./chunk-WFMP6TZN.js";
13
13
  import "./chunk-MXSQYVCK.js";
14
14
  import "./chunk-RCUKSVMF.js";
15
15
  import "./chunk-HXQF6XTL.js";
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkNSSX7USQcjs = require('./chunk-NSSX7USQ.cjs');
13
+ var _chunkI5NVZORXcjs = require('./chunk-I5NVZORX.cjs');
14
14
  require('./chunk-VL6L4GDA.cjs');
15
15
 
16
16
 
@@ -22,5 +22,5 @@ require('./chunk-VL6L4GDA.cjs');
22
22
 
23
23
 
24
24
 
25
- exports.ListPagination = _chunkNSSX7USQcjs.ListPagination; exports.Pagination = _chunkNSSX7USQcjs.Pagination; exports.PaginationContent = _chunkNSSX7USQcjs.PaginationContent; exports.PaginationEllipsis = _chunkNSSX7USQcjs.PaginationEllipsis; exports.PaginationItem = _chunkNSSX7USQcjs.PaginationItem; exports.PaginationLink = _chunkNSSX7USQcjs.PaginationLink; exports.PaginationNext = _chunkNSSX7USQcjs.PaginationNext; exports.PaginationPrevious = _chunkNSSX7USQcjs.PaginationPrevious; exports.getPageNumbers = _chunkNSSX7USQcjs.getPageNumbers;
25
+ exports.ListPagination = _chunkI5NVZORXcjs.ListPagination; exports.Pagination = _chunkI5NVZORXcjs.Pagination; exports.PaginationContent = _chunkI5NVZORXcjs.PaginationContent; exports.PaginationEllipsis = _chunkI5NVZORXcjs.PaginationEllipsis; exports.PaginationItem = _chunkI5NVZORXcjs.PaginationItem; exports.PaginationLink = _chunkI5NVZORXcjs.PaginationLink; exports.PaginationNext = _chunkI5NVZORXcjs.PaginationNext; exports.PaginationPrevious = _chunkI5NVZORXcjs.PaginationPrevious; exports.getPageNumbers = _chunkI5NVZORXcjs.getPageNumbers;
26
26
  //# sourceMappingURL=pagination.cjs.map
@@ -10,7 +10,7 @@ import {
10
10
  PaginationNext,
11
11
  PaginationPrevious,
12
12
  getPageNumbers
13
- } from "./chunk-3VN3FX2Q.js";
13
+ } from "./chunk-OJ5G4BLS.js";
14
14
  import "./chunk-QICSGVX3.js";
15
15
  export {
16
16
  ListPagination,
@@ -1,8 +1,30 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/price-format.ts
2
+ var formatDefaults = {
3
+ currency: "USD",
4
+ locale: "en-US",
5
+ precision: 2
6
+ };
7
+ function createFormatPrice(config = {}) {
8
+ const {
9
+ currency,
10
+ locale,
11
+ precision: defaultPrecision
12
+ } = {
13
+ ...formatDefaults,
14
+ ...config
15
+ };
16
+ return function formatPrice(value, options) {
17
+ const p = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.precision]), () => ( defaultPrecision));
18
+ const displayValue = _optionalChain([options, 'optionalAccess', _2 => _2.quantity]) !== void 0 ? value * options.quantity : value;
19
+ return new Intl.NumberFormat(locale, {
20
+ style: "currency",
21
+ currency,
22
+ minimumFractionDigits: p,
23
+ maximumFractionDigits: p
24
+ }).format(displayValue);
25
+ };
26
+ }
2
27
 
3
28
 
4
- var _chunkVLZDTWPRcjs = require('./chunk-VLZDTWPR.cjs');
5
-
6
-
7
- exports.createFormatPrice = _chunkVLZDTWPRcjs.createFormatPrice;
29
+ exports.createFormatPrice = createFormatPrice;
8
30
  //# sourceMappingURL=price-format.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs"],"names":[],"mappings":"AAAA,qFAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,gEAAC","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs","../src/price-format.ts"],"names":[],"mappings":"AAAA;ACqBA,IAAM,eAAA,EAA8C;AAAA,EAClD,QAAA,EAAU,KAAA;AAAA,EACV,MAAA,EAAQ,OAAA;AAAA,EACR,SAAA,EAAW;AACb,CAAA;AAMO,SAAS,iBAAA,CACd,OAAA,EAA4B,CAAC,CAAA,EAC4B;AACzD,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA,EAAW;AAAA,EACb,EAAA,EAAI;AAAA,IACF,GAAG,cAAA;AAAA,IACH,GAAG;AAAA,EACL,CAAA;AAEA,EAAA,OAAO,SAAS,WAAA,CAAY,KAAA,EAAe,OAAA,EAAsC;AAC/E,IAAA,MAAM,EAAA,mCAAI,OAAA,2BAAS,WAAA,UAAa,kBAAA;AAChC,IAAA,MAAM,aAAA,kBAAe,OAAA,6BAAS,WAAA,IAAa,KAAA,EAAA,EAAY,MAAA,EAAQ,OAAA,CAAQ,SAAA,EAAW,KAAA;AAClF,IAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ;AAAA,MACnC,KAAA,EAAO,UAAA;AAAA,MACP,QAAA;AAAA,MACA,qBAAA,EAAuB,CAAA;AAAA,MACvB,qBAAA,EAAuB;AAAA,IACzB,CAAC,CAAA,CAAE,MAAA,CAAO,YAAY,CAAA;AAAA,EACxB,CAAA;AACF;AD3BA;AACE;AACF,8CAAC","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price-format.cjs","sourcesContent":[null,"// ---------------------------------------------------------------------------\n// Pure formatting logic — no React, no \"use client\".\n// Safe to import in server components.\n// ---------------------------------------------------------------------------\n\nexport interface PriceFormatConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n}\n\nexport interface FormatPriceOptions {\n /** Override precision for this call. */\n precision?: number;\n /** Multiply value by quantity before formatting. */\n quantity?: number;\n}\n\nconst formatDefaults: Required<PriceFormatConfig> = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n};\n\n/**\n * Create a pure price-formatting function. Server-safe (no React dependency).\n * Use {@link createPrice} in client components for the full Price component.\n */\nexport function createFormatPrice(\n config: PriceFormatConfig = {},\n): (value: number, options?: FormatPriceOptions) => string {\n const {\n currency,\n locale,\n precision: defaultPrecision,\n } = {\n ...formatDefaults,\n ...config,\n };\n\n return function formatPrice(value: number, options?: FormatPriceOptions): string {\n const p = options?.precision ?? defaultPrecision;\n const displayValue = options?.quantity !== undefined ? value * options.quantity : value;\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n minimumFractionDigits: p,\n maximumFractionDigits: p,\n }).format(displayValue);\n };\n}\n"]}
@@ -1,7 +1,29 @@
1
- "use client";
2
- import {
3
- createFormatPrice
4
- } from "./chunk-DZDC4HHK.js";
1
+ // src/price-format.ts
2
+ var formatDefaults = {
3
+ currency: "USD",
4
+ locale: "en-US",
5
+ precision: 2
6
+ };
7
+ function createFormatPrice(config = {}) {
8
+ const {
9
+ currency,
10
+ locale,
11
+ precision: defaultPrecision
12
+ } = {
13
+ ...formatDefaults,
14
+ ...config
15
+ };
16
+ return function formatPrice(value, options) {
17
+ const p = options?.precision ?? defaultPrecision;
18
+ const displayValue = options?.quantity !== void 0 ? value * options.quantity : value;
19
+ return new Intl.NumberFormat(locale, {
20
+ style: "currency",
21
+ currency,
22
+ minimumFractionDigits: p,
23
+ maximumFractionDigits: p
24
+ }).format(displayValue);
25
+ };
26
+ }
5
27
  export {
6
28
  createFormatPrice
7
29
  };
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/price-format.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Pure formatting logic — no React, no \"use client\".\n// Safe to import in server components.\n// ---------------------------------------------------------------------------\n\nexport interface PriceFormatConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n}\n\nexport interface FormatPriceOptions {\n /** Override precision for this call. */\n precision?: number;\n /** Multiply value by quantity before formatting. */\n quantity?: number;\n}\n\nconst formatDefaults: Required<PriceFormatConfig> = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n};\n\n/**\n * Create a pure price-formatting function. Server-safe (no React dependency).\n * Use {@link createPrice} in client components for the full Price component.\n */\nexport function createFormatPrice(\n config: PriceFormatConfig = {},\n): (value: number, options?: FormatPriceOptions) => string {\n const {\n currency,\n locale,\n precision: defaultPrecision,\n } = {\n ...formatDefaults,\n ...config,\n };\n\n return function formatPrice(value: number, options?: FormatPriceOptions): string {\n const p = options?.precision ?? defaultPrecision;\n const displayValue = options?.quantity !== undefined ? value * options.quantity : value;\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n minimumFractionDigits: p,\n maximumFractionDigits: p,\n }).format(displayValue);\n };\n}\n"],"mappings":";AAqBA,IAAM,iBAA8C;AAAA,EAClD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AACb;AAMO,SAAS,kBACd,SAA4B,CAAC,GAC4B;AACzD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb,IAAI;AAAA,IACF,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,SAAO,SAAS,YAAY,OAAe,SAAsC;AAC/E,UAAM,IAAI,SAAS,aAAa;AAChC,UAAM,eAAe,SAAS,aAAa,SAAY,QAAQ,QAAQ,WAAW;AAClF,WAAO,IAAI,KAAK,aAAa,QAAQ;AAAA,MACnC,OAAO;AAAA,MACP;AAAA,MACA,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACzB,CAAC,EAAE,OAAO,YAAY;AAAA,EACxB;AACF;","names":[]}
package/dist/price.cjs CHANGED
@@ -1,11 +1,37 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
2
  "use client";
3
3
 
4
+ // src/price.tsx
5
+ var _web = require('@simpleapps-com/augur-utils/web');
4
6
 
5
- var _chunkVLZDTWPRcjs = require('./chunk-VLZDTWPR.cjs');
7
+ // src/price-format.ts
8
+ var formatDefaults = {
9
+ currency: "USD",
10
+ locale: "en-US",
11
+ precision: 2
12
+ };
13
+ function createFormatPrice(config = {}) {
14
+ const {
15
+ currency,
16
+ locale,
17
+ precision: defaultPrecision
18
+ } = {
19
+ ...formatDefaults,
20
+ ...config
21
+ };
22
+ return function formatPrice(value, options) {
23
+ const p = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.precision]), () => ( defaultPrecision));
24
+ const displayValue = _optionalChain([options, 'optionalAccess', _2 => _2.quantity]) !== void 0 ? value * options.quantity : value;
25
+ return new Intl.NumberFormat(locale, {
26
+ style: "currency",
27
+ currency,
28
+ minimumFractionDigits: p,
29
+ maximumFractionDigits: p
30
+ }).format(displayValue);
31
+ };
32
+ }
6
33
 
7
34
  // src/price.tsx
8
- var _web = require('@simpleapps-com/augur-utils/web');
9
35
  var _jsxruntime = require('react/jsx-runtime');
10
36
  var defaults = {
11
37
  currency: "USD",
@@ -23,7 +49,7 @@ function createPrice(config = {}) {
23
49
  uomSeparator,
24
50
  classNames: factoryClassNames
25
51
  } = { ...defaults, ...config };
26
- const formatPrice = _chunkVLZDTWPRcjs.createFormatPrice.call(void 0, { currency, locale, precision });
52
+ const formatPrice = createFormatPrice({ currency, locale, precision });
27
53
  const slotKeys = [
28
54
  "amount",
29
55
  "uom",
@@ -36,7 +62,7 @@ function createPrice(config = {}) {
36
62
  if (!factoryClassNames && !instance) return {};
37
63
  const result = {};
38
64
  for (const key of slotKeys) {
39
- const merged = _web.cn.call(void 0, _optionalChain([factoryClassNames, 'optionalAccess', _ => _[key]]), _optionalChain([instance, 'optionalAccess', _2 => _2[key]]));
65
+ const merged = _web.cn.call(void 0, _optionalChain([factoryClassNames, 'optionalAccess', _3 => _3[key]]), _optionalChain([instance, 'optionalAccess', _4 => _4[key]]));
40
66
  if (merged) result[key] = merged;
41
67
  }
42
68
  return result;
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","../src/price.tsx"],"names":["slots"],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","sourcesContent":[null,"\"use client\";\n\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { createFormatPrice } from \"./price-format\";\nimport type { FormatPriceOptions } from \"./price-format\";\n\n// Re-export server-safe types so client consumers get everything from one path\nexport type { PriceFormatConfig, FormatPriceOptions } from \"./price-format\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PriceClassNames {\n /** The formatted amount text. */\n amount?: string;\n /** The UOM label (e.g. \"EACH\"). */\n uom?: string;\n /** The separator between price and UOM (e.g. \"/\"). */\n separator?: string;\n /** The zero-price label (e.g. \"Call for Price\"). */\n zero?: string;\n /** The loading skeleton. */\n skeleton?: string;\n /** The strikethrough original price. */\n original?: string;\n}\n\nexport interface PriceConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n /** Label shown when value is 0. Default: `\"Call for Price\"`. */\n zeroLabel?: string;\n /** Separator between price and UOM. Default: `\"/\"`. */\n uomSeparator?: string;\n /** Default class names for sub-elements. */\n classNames?: PriceClassNames;\n}\n\ntype PricePropsBase = {\n /** Unit price. */\n value?: number;\n /** Quantity — multiplied by value for extended price. */\n quantity?: number;\n /** Unit of measure label (e.g. \"EACH\", \"FT\"). */\n uom?: string;\n /** Override precision for this instance. */\n precision?: number;\n /** Original price shown as strikethrough for sale display. */\n originalValue?: number;\n /** Additional class names for the root element. */\n className?: string;\n /** Class names for sub-elements, merged with factory defaults. */\n classNames?: PriceClassNames;\n};\n\nexport type PriceProps =\n | (PricePropsBase & { loading?: false })\n | { loading: true; className?: string; classNames?: PriceClassNames };\n\nexport interface CreatePriceResult {\n Price: React.FC<PriceProps>;\n formatPrice: (value: number, options?: FormatPriceOptions) => string;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nconst defaults = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n zeroLabel: \"Call for Price\",\n uomSeparator: \"/\",\n} as const;\n\n/**\n * Factory that creates a `Price` component and a `formatPrice` function\n * pre-configured with site-level currency/locale/precision.\n *\n * @example\n * ```tsx\n * // lib/price.ts -- one-time site config\n * import { createPrice } from \"@simpleapps-com/augur-web/price\";\n * export const { Price, formatPrice } = createPrice({\n * currency: \"USD\",\n * zeroLabel: \"Call for Price\",\n * });\n *\n * // components/ProductCard.tsx\n * <Price value={item.price1} uom={item.default_selling_unit} />\n * ```\n */\nexport function createPrice(config: PriceConfig = {}): CreatePriceResult {\n const {\n currency,\n locale,\n precision,\n zeroLabel,\n uomSeparator,\n classNames: factoryClassNames,\n } = { ...defaults, ...config };\n\n const formatPrice = createFormatPrice({ currency, locale, precision });\n\n const slotKeys: (keyof PriceClassNames)[] = [\n \"amount\",\n \"uom\",\n \"separator\",\n \"zero\",\n \"skeleton\",\n \"original\",\n ];\n\n function mergeClassNames(instance?: PriceClassNames): PriceClassNames {\n if (!factoryClassNames && !instance) return {};\n const result: PriceClassNames = {};\n for (const key of slotKeys) {\n const merged = cn(factoryClassNames?.[key], instance?.[key]);\n if (merged) result[key] = merged;\n }\n return result;\n }\n\n function Price(props: PriceProps) {\n if (\"loading\" in props && props.loading) {\n const slots = mergeClassNames(props.classNames);\n return (\n <span\n className={cn(\n \"bg-muted inline-block h-4 w-16 animate-pulse rounded\",\n slots.skeleton,\n props.className,\n )}\n />\n );\n }\n\n const {\n value = 0,\n quantity,\n uom,\n precision: instancePrecision,\n originalValue,\n className,\n classNames: instanceClassNames,\n } = props as PricePropsBase;\n\n const slots = mergeClassNames(instanceClassNames);\n\n if (value === 0 && originalValue === undefined) {\n return (\n <span className={cn(\"text-muted-foreground\", slots.zero, className)}>{zeroLabel}</span>\n );\n }\n\n const formatted = formatPrice(value, {\n precision: instancePrecision,\n quantity,\n });\n\n return (\n <span className={className}>\n {originalValue !== undefined && (\n <s className={cn(\"text-muted-foreground mr-1\", slots.original)}>\n {formatPrice(originalValue, { precision: instancePrecision })}\n </s>\n )}\n <span className={slots.amount}>{formatted}</span>\n {uom && (\n <>\n <span className={cn(\"ml-1\", slots.separator)}>{uomSeparator}</span>\n <span className={cn(\"text-muted-foreground ml-1\", slots.uom)}>{uom}</span>\n </>\n )}\n </span>\n );\n }\n\n Price.displayName = \"Price\";\n\n return { Price, formatPrice };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","../src/price.tsx","../src/price-format.ts"],"names":["slots"],"mappings":"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","file":"/home/runner/work/augur-packages/augur-packages/packages/augur-web/dist/price.cjs","sourcesContent":[null,"\"use client\";\n\nimport { cn } from \"@simpleapps-com/augur-utils/web\";\nimport { createFormatPrice } from \"./price-format\";\nimport type { FormatPriceOptions } from \"./price-format\";\n\n// Re-export server-safe types so client consumers get everything from one path\nexport type { PriceFormatConfig, FormatPriceOptions } from \"./price-format\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PriceClassNames {\n /** The formatted amount text. */\n amount?: string;\n /** The UOM label (e.g. \"EACH\"). */\n uom?: string;\n /** The separator between price and UOM (e.g. \"/\"). */\n separator?: string;\n /** The zero-price label (e.g. \"Call for Price\"). */\n zero?: string;\n /** The loading skeleton. */\n skeleton?: string;\n /** The strikethrough original price. */\n original?: string;\n}\n\nexport interface PriceConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n /** Label shown when value is 0. Default: `\"Call for Price\"`. */\n zeroLabel?: string;\n /** Separator between price and UOM. Default: `\"/\"`. */\n uomSeparator?: string;\n /** Default class names for sub-elements. */\n classNames?: PriceClassNames;\n}\n\ntype PricePropsBase = {\n /** Unit price. */\n value?: number;\n /** Quantity — multiplied by value for extended price. */\n quantity?: number;\n /** Unit of measure label (e.g. \"EACH\", \"FT\"). */\n uom?: string;\n /** Override precision for this instance. */\n precision?: number;\n /** Original price shown as strikethrough for sale display. */\n originalValue?: number;\n /** Additional class names for the root element. */\n className?: string;\n /** Class names for sub-elements, merged with factory defaults. */\n classNames?: PriceClassNames;\n};\n\nexport type PriceProps =\n | (PricePropsBase & { loading?: false })\n | { loading: true; className?: string; classNames?: PriceClassNames };\n\nexport interface CreatePriceResult {\n Price: React.FC<PriceProps>;\n formatPrice: (value: number, options?: FormatPriceOptions) => string;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nconst defaults = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n zeroLabel: \"Call for Price\",\n uomSeparator: \"/\",\n} as const;\n\n/**\n * Factory that creates a `Price` component and a `formatPrice` function\n * pre-configured with site-level currency/locale/precision.\n *\n * @example\n * ```tsx\n * // lib/price.ts -- one-time site config\n * import { createPrice } from \"@simpleapps-com/augur-web/price\";\n * export const { Price, formatPrice } = createPrice({\n * currency: \"USD\",\n * zeroLabel: \"Call for Price\",\n * });\n *\n * // components/ProductCard.tsx\n * <Price value={item.price1} uom={item.default_selling_unit} />\n * ```\n */\nexport function createPrice(config: PriceConfig = {}): CreatePriceResult {\n const {\n currency,\n locale,\n precision,\n zeroLabel,\n uomSeparator,\n classNames: factoryClassNames,\n } = { ...defaults, ...config };\n\n const formatPrice = createFormatPrice({ currency, locale, precision });\n\n const slotKeys: (keyof PriceClassNames)[] = [\n \"amount\",\n \"uom\",\n \"separator\",\n \"zero\",\n \"skeleton\",\n \"original\",\n ];\n\n function mergeClassNames(instance?: PriceClassNames): PriceClassNames {\n if (!factoryClassNames && !instance) return {};\n const result: PriceClassNames = {};\n for (const key of slotKeys) {\n const merged = cn(factoryClassNames?.[key], instance?.[key]);\n if (merged) result[key] = merged;\n }\n return result;\n }\n\n function Price(props: PriceProps) {\n if (\"loading\" in props && props.loading) {\n const slots = mergeClassNames(props.classNames);\n return (\n <span\n className={cn(\n \"bg-muted inline-block h-4 w-16 animate-pulse rounded\",\n slots.skeleton,\n props.className,\n )}\n />\n );\n }\n\n const {\n value = 0,\n quantity,\n uom,\n precision: instancePrecision,\n originalValue,\n className,\n classNames: instanceClassNames,\n } = props as PricePropsBase;\n\n const slots = mergeClassNames(instanceClassNames);\n\n if (value === 0 && originalValue === undefined) {\n return (\n <span className={cn(\"text-muted-foreground\", slots.zero, className)}>{zeroLabel}</span>\n );\n }\n\n const formatted = formatPrice(value, {\n precision: instancePrecision,\n quantity,\n });\n\n return (\n <span className={className}>\n {originalValue !== undefined && (\n <s className={cn(\"text-muted-foreground mr-1\", slots.original)}>\n {formatPrice(originalValue, { precision: instancePrecision })}\n </s>\n )}\n <span className={slots.amount}>{formatted}</span>\n {uom && (\n <>\n <span className={cn(\"ml-1\", slots.separator)}>{uomSeparator}</span>\n <span className={cn(\"text-muted-foreground ml-1\", slots.uom)}>{uom}</span>\n </>\n )}\n </span>\n );\n }\n\n Price.displayName = \"Price\";\n\n return { Price, formatPrice };\n}\n","// ---------------------------------------------------------------------------\n// Pure formatting logic — no React, no \"use client\".\n// Safe to import in server components.\n// ---------------------------------------------------------------------------\n\nexport interface PriceFormatConfig {\n /** ISO 4217 currency code. Default: `\"USD\"`. */\n currency?: string;\n /** BCP 47 locale. Default: `\"en-US\"`. */\n locale?: string;\n /** Decimal places. Default: `2`. */\n precision?: number;\n}\n\nexport interface FormatPriceOptions {\n /** Override precision for this call. */\n precision?: number;\n /** Multiply value by quantity before formatting. */\n quantity?: number;\n}\n\nconst formatDefaults: Required<PriceFormatConfig> = {\n currency: \"USD\",\n locale: \"en-US\",\n precision: 2,\n};\n\n/**\n * Create a pure price-formatting function. Server-safe (no React dependency).\n * Use {@link createPrice} in client components for the full Price component.\n */\nexport function createFormatPrice(\n config: PriceFormatConfig = {},\n): (value: number, options?: FormatPriceOptions) => string {\n const {\n currency,\n locale,\n precision: defaultPrecision,\n } = {\n ...formatDefaults,\n ...config,\n };\n\n return function formatPrice(value: number, options?: FormatPriceOptions): string {\n const p = options?.precision ?? defaultPrecision;\n const displayValue = options?.quantity !== undefined ? value * options.quantity : value;\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n minimumFractionDigits: p,\n maximumFractionDigits: p,\n }).format(displayValue);\n };\n}\n"]}
package/dist/price.d.cts CHANGED
@@ -1,5 +1,17 @@
1
- import { FormatPriceOptions } from './price-format.cjs';
2
- export { PriceFormatConfig } from './price-format.cjs';
1
+ interface PriceFormatConfig {
2
+ /** ISO 4217 currency code. Default: `"USD"`. */
3
+ currency?: string;
4
+ /** BCP 47 locale. Default: `"en-US"`. */
5
+ locale?: string;
6
+ /** Decimal places. Default: `2`. */
7
+ precision?: number;
8
+ }
9
+ interface FormatPriceOptions {
10
+ /** Override precision for this call. */
11
+ precision?: number;
12
+ /** Multiply value by quantity before formatting. */
13
+ quantity?: number;
14
+ }
3
15
 
4
16
  interface PriceClassNames {
5
17
  /** The formatted amount text. */
@@ -75,4 +87,4 @@ interface CreatePriceResult {
75
87
  */
76
88
  declare function createPrice(config?: PriceConfig): CreatePriceResult;
77
89
 
78
- export { type CreatePriceResult, FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceProps, createPrice };
90
+ export { type CreatePriceResult, type FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceFormatConfig, type PriceProps, createPrice };
package/dist/price.d.ts CHANGED
@@ -1,5 +1,17 @@
1
- import { FormatPriceOptions } from './price-format.js';
2
- export { PriceFormatConfig } from './price-format.js';
1
+ interface PriceFormatConfig {
2
+ /** ISO 4217 currency code. Default: `"USD"`. */
3
+ currency?: string;
4
+ /** BCP 47 locale. Default: `"en-US"`. */
5
+ locale?: string;
6
+ /** Decimal places. Default: `2`. */
7
+ precision?: number;
8
+ }
9
+ interface FormatPriceOptions {
10
+ /** Override precision for this call. */
11
+ precision?: number;
12
+ /** Multiply value by quantity before formatting. */
13
+ quantity?: number;
14
+ }
3
15
 
4
16
  interface PriceClassNames {
5
17
  /** The formatted amount text. */
@@ -75,4 +87,4 @@ interface CreatePriceResult {
75
87
  */
76
88
  declare function createPrice(config?: PriceConfig): CreatePriceResult;
77
89
 
78
- export { type CreatePriceResult, FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceProps, createPrice };
90
+ export { type CreatePriceResult, type FormatPriceOptions, type PriceClassNames, type PriceConfig, type PriceFormatConfig, type PriceProps, createPrice };
package/dist/price.js CHANGED
@@ -1,11 +1,37 @@
1
1
  "use client";
2
2
  "use client";
3
- import {
4
- createFormatPrice
5
- } from "./chunk-DZDC4HHK.js";
6
3
 
7
4
  // src/price.tsx
8
5
  import { cn } from "@simpleapps-com/augur-utils/web";
6
+
7
+ // src/price-format.ts
8
+ var formatDefaults = {
9
+ currency: "USD",
10
+ locale: "en-US",
11
+ precision: 2
12
+ };
13
+ function createFormatPrice(config = {}) {
14
+ const {
15
+ currency,
16
+ locale,
17
+ precision: defaultPrecision
18
+ } = {
19
+ ...formatDefaults,
20
+ ...config
21
+ };
22
+ return function formatPrice(value, options) {
23
+ const p = options?.precision ?? defaultPrecision;
24
+ const displayValue = options?.quantity !== void 0 ? value * options.quantity : value;
25
+ return new Intl.NumberFormat(locale, {
26
+ style: "currency",
27
+ currency,
28
+ minimumFractionDigits: p,
29
+ maximumFractionDigits: p
30
+ }).format(displayValue);
31
+ };
32
+ }
33
+
34
+ // src/price.tsx
9
35
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
36
  var defaults = {
11
37
  currency: "USD",