@hexclave/dashboard-ui-components 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/alert.js +4 -4
- package/dist/components/alert.js.map +1 -1
- package/dist/components/analytics-chart/analytics-chart-pie.js +33 -11
- package/dist/components/analytics-chart/analytics-chart-pie.js.map +1 -1
- package/dist/components/analytics-chart/analytics-chart.js +3 -3
- package/dist/components/analytics-chart/analytics-chart.js.map +1 -1
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.js +4 -4
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.js.map +1 -1
- package/dist/components/analytics-chart/types.d.ts +1 -0
- package/dist/components/analytics-chart/types.d.ts.map +1 -1
- package/dist/components/analytics-chart/types.js.map +1 -1
- package/dist/components/badge.js +2 -2
- package/dist/components/badge.js.map +1 -1
- package/dist/components/button.js +11 -11
- package/dist/components/button.js.map +1 -1
- package/dist/components/card.js +7 -7
- package/dist/components/card.js.map +1 -1
- package/dist/components/chart-card.js +3 -3
- package/dist/components/chart-card.js.map +1 -1
- package/dist/components/chart-container.js +2 -2
- package/dist/components/chart-container.js.map +1 -1
- package/dist/components/chart-legend.js +3 -3
- package/dist/components/chart-legend.js.map +1 -1
- package/dist/components/chart-tooltip.js +7 -7
- package/dist/components/chart-tooltip.js.map +1 -1
- package/dist/components/data-grid/data-grid-toolbar.js +7 -7
- package/dist/components/data-grid/data-grid-toolbar.js.map +1 -1
- package/dist/components/data-grid/data-grid.js +16 -16
- package/dist/components/data-grid/data-grid.js.map +1 -1
- package/dist/components/data-grid/state.js +2 -2
- package/dist/components/data-grid/state.js.map +1 -1
- package/dist/components/dialog.js +22 -22
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/empty-state.js +2 -2
- package/dist/components/empty-state.js.map +1 -1
- package/dist/components/input.js +8 -8
- package/dist/components/input.js.map +1 -1
- package/dist/components/metric-card.js +5 -5
- package/dist/components/metric-card.js.map +1 -1
- package/dist/components/pill-toggle.js +11 -10
- package/dist/components/pill-toggle.js.map +1 -1
- package/dist/components/progress-bar.js +4 -4
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/separator.js +2 -2
- package/dist/components/separator.js.map +1 -1
- package/dist/components/skeleton.js +2 -2
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/table.js +14 -14
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +10 -10
- package/dist/components/tabs.js.map +1 -1
- package/dist/dashboard-ui-components.global.js +1647 -1605
- package/dist/dashboard-ui-components.global.js.map +4 -4
- package/dist/esm/components/alert.js.map +1 -1
- package/dist/esm/components/analytics-chart/analytics-chart-pie.js +33 -11
- package/dist/esm/components/analytics-chart/analytics-chart-pie.js.map +1 -1
- package/dist/esm/components/analytics-chart/analytics-chart.js.map +1 -1
- package/dist/esm/components/analytics-chart/default-analytics-chart-tooltip.js.map +1 -1
- package/dist/esm/components/analytics-chart/types.d.ts +1 -0
- package/dist/esm/components/analytics-chart/types.d.ts.map +1 -1
- package/dist/esm/components/analytics-chart/types.js.map +1 -1
- package/dist/esm/components/badge.js.map +1 -1
- package/dist/esm/components/button.js.map +1 -1
- package/dist/esm/components/card.js.map +1 -1
- package/dist/esm/components/chart-card.js.map +1 -1
- package/dist/esm/components/chart-container.js.map +1 -1
- package/dist/esm/components/chart-legend.js.map +1 -1
- package/dist/esm/components/chart-tooltip.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid-toolbar.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid.js.map +1 -1
- package/dist/esm/components/data-grid/state.js.map +1 -1
- package/dist/esm/components/dialog.js.map +1 -1
- package/dist/esm/components/empty-state.js.map +1 -1
- package/dist/esm/components/input.js.map +1 -1
- package/dist/esm/components/metric-card.js.map +1 -1
- package/dist/esm/components/pill-toggle.js +1 -0
- package/dist/esm/components/pill-toggle.js.map +1 -1
- package/dist/esm/components/progress-bar.js.map +1 -1
- package/dist/esm/components/separator.js.map +1 -1
- package/dist/esm/components/skeleton.js.map +1 -1
- package/dist/esm/components/table.js.map +1 -1
- package/dist/esm/components/tabs.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","names":["DEFAULT_COL_WIDTH"],"sources":["../../../src/components/data-grid/state.ts"],"sourcesContent":["import { stringCompare } from \"@stackframe/stack-shared/dist/utils/strings\";\nimport { clampColumnWidth, DEFAULT_COL_WIDTH } from \"./data-grid-sizing\";\nimport type {\n DataGridColumnDef,\n DataGridDateDisplay,\n DataGridDateFormat,\n DataGridPaginationModel,\n DataGridSortModel,\n DataGridState,\n} from \"./types\";\n\n/**\n * Build the initial `DataGridState` for a set of columns. Pass this as the\n * lazy initializer to `useState` — never hand-assemble the state object.\n *\n * ```tsx\n * const [gridState, setGridState] = React.useState(() =>\n * createDefaultDataGridState(columns)\n * );\n * ```\n */\nexport function createDefaultDataGridState(\n columns: readonly DataGridColumnDef<any>[],\n): DataGridState {\n const columnWidths: Record<string, number> = {};\n const columnOrder: string[] = [];\n\n for (const col of columns) {\n columnWidths[col.id] = clampColumnWidth(col, col.width ?? DEFAULT_COL_WIDTH);\n columnOrder.push(col.id);\n }\n\n return {\n sorting: [],\n columnVisibility: {},\n columnWidths,\n columnPinning: { left: [], right: [] },\n columnOrder,\n pagination: { pageIndex: 0, pageSize: 50 },\n selection: { selectedIds: new Set(), anchorId: null },\n dateDisplay: \"relative\",\n quickSearch: \"\",\n };\n}\n\n// ─── Column value resolution ─────────────────────────────────────────\n\nexport function resolveColumnValue<TRow>(\n col: DataGridColumnDef<TRow>,\n row: TRow,\n): unknown {\n if (typeof col.accessor === \"function\") return col.accessor(row);\n const key = (col.accessor ?? col.id) as keyof TRow;\n return row[key];\n}\n\n// ─── Default sort comparator (used by client-mode useDataSource) ────\n\nfunction defaultComparator(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n return stringCompare(String(a), String(b));\n}\n\nexport function buildRowComparator<TRow>(\n sortModel: DataGridSortModel,\n columns: readonly DataGridColumnDef<TRow>[],\n): ((a: TRow, b: TRow) => number) | null {\n if (sortModel.length === 0) return null;\n const colMap = new Map(columns.map((c) => [c.id, c]));\n return (a, b) => {\n for (const { columnId, direction } of sortModel) {\n const col = colMap.get(columnId);\n if (!col) continue;\n const va = resolveColumnValue(col, a);\n const vb = resolveColumnValue(col, b);\n const cmp = col.sortComparator ? col.sortComparator(va, vb) : defaultComparator(va, vb);\n if (cmp !== 0) return direction === \"asc\" ? cmp : -cmp;\n }\n return 0;\n };\n}\n\n// ─── Pagination ──────────────────────────────────────────────────────\n\nexport function paginateRows<TRow>(\n rows: readonly TRow[],\n pagination: DataGridPaginationModel,\n): TRow[] {\n const start = pagination.pageIndex * pagination.pageSize;\n return rows.slice(start, start + pagination.pageSize) as TRow[];\n}\n\n// ─── Quick search ────────────────────────────────────────────────────\n\n/** Default row matcher: case-insensitive substring across every column. */\nexport function defaultMatchRow<TRow>(\n row: TRow,\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n): boolean {\n for (const col of columns) {\n const v = resolveColumnValue(col, row);\n if (v == null) continue;\n if (String(v).toLowerCase().includes(query)) return true;\n }\n return false;\n}\n\nexport function applyQuickSearch<TRow>(\n rows: readonly TRow[],\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n matchRow: (\n row: TRow,\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n ) => boolean = defaultMatchRow,\n): readonly TRow[] {\n const trimmed = query.trim().toLowerCase();\n if (!trimmed) return rows;\n return rows.filter((r) => matchRow(r, trimmed, columns));\n}\n\n// ─── Date helpers ────────────────────────────────────────────────────\n\nexport function defaultParseDate(value: unknown): Date | null {\n if (value == null) return null;\n if (value instanceof Date) return isNaN(value.getTime()) ? null : value;\n if (typeof value === \"number\" || typeof value === \"string\") {\n const d = new Date(value);\n return isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\nconst DIVISIONS: Array<{ amount: number; unit: Intl.RelativeTimeFormatUnit }> = [\n { amount: 60, unit: \"second\" },\n { amount: 60, unit: \"minute\" },\n { amount: 24, unit: \"hour\" },\n { amount: 7, unit: \"day\" },\n { amount: 4.34524, unit: \"week\" },\n { amount: 12, unit: \"month\" },\n { amount: Number.POSITIVE_INFINITY, unit: \"year\" },\n];\n\nconst relativeTimeFormatterCache = new Map<string, Intl.RelativeTimeFormat>();\nfunction getRelativeTimeFormatter(locale?: string): Intl.RelativeTimeFormat {\n const key = locale ?? \"__default__\";\n let cached = relativeTimeFormatterCache.get(key);\n if (cached == null) {\n cached = new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" });\n relativeTimeFormatterCache.set(key, cached);\n }\n return cached;\n}\n\nexport function defaultFormatRelative(date: Date): string {\n const rtf = getRelativeTimeFormatter();\n // Wall-clock comparison to \"now\" (e.g. \"5 minutes ago\"). performance.now()\n // would be wrong here — it's a monotonic timer, not a wall-clock instant.\n let duration = (date.getTime() - Date.now()) / 1000;\n for (const div of DIVISIONS) {\n if (Math.abs(duration) < div.amount) return rtf.format(Math.round(duration), div.unit);\n duration /= div.amount;\n }\n return rtf.format(Math.round(duration), \"year\");\n}\n\nexport function defaultFormatAbsolute(date: Date): string {\n return date.toLocaleString();\n}\n\nexport function formatGridDate(\n value: unknown,\n mode: DataGridDateDisplay,\n opts?: {\n parseValue?: (value: unknown) => Date | null;\n dateFormat?: DataGridDateFormat;\n },\n): { display: string | null; tooltip: string | null } {\n const parse = opts?.parseValue ?? defaultParseDate;\n const date = parse(value);\n if (!date) return { display: null, tooltip: null };\n const relative = opts?.dateFormat?.relative ?? defaultFormatRelative;\n const absolute = opts?.dateFormat?.absolute ?? defaultFormatAbsolute;\n const tooltip = absolute(date);\n const display = mode === \"relative\" ? relative(date) : tooltip;\n return { display, tooltip };\n}\n\n// ─── CSV Export ──────────────────────────────────────────────────────\n\nexport function exportToCsv<TRow>(\n rows: readonly TRow[],\n columns: readonly DataGridColumnDef<TRow>[],\n filename: string,\n): void {\n const header = columns.map((col) =>\n typeof col.header === \"string\" ? col.header : col.id,\n );\n const csvRows = rows.map((row) =>\n columns.map((col) => {\n const val = resolveColumnValue(col, row);\n const formatted = col.formatValue\n ? String((col.formatValue(val, row) as string | null | undefined) ?? \"\")\n : String(val ?? \"\");\n if (formatted.includes(\",\") || formatted.includes('\"') || formatted.includes(\"\\n\")) {\n return `\"${formatted.replace(/\"/g, '\"\"')}\"`;\n }\n return formatted;\n }),\n );\n // UTF-8 BOM so Excel opens the CSV as UTF-8.\n const csvContent = \"\\uFEFF\" + [\n header.join(\",\"),\n ...csvRows.map((row) => row.join(\",\")),\n ].join(\"\\n\");\n\n const blob = new Blob([csvContent], { 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 document.body.appendChild(link);\n try {\n link.click();\n } finally {\n link.remove();\n URL.revokeObjectURL(url);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"state.js","names":["DEFAULT_COL_WIDTH"],"sources":["../../../src/components/data-grid/state.ts"],"sourcesContent":["import { stringCompare } from \"@hexclave/shared/dist/utils/strings\";\nimport { clampColumnWidth, DEFAULT_COL_WIDTH } from \"./data-grid-sizing\";\nimport type {\n DataGridColumnDef,\n DataGridDateDisplay,\n DataGridDateFormat,\n DataGridPaginationModel,\n DataGridSortModel,\n DataGridState,\n} from \"./types\";\n\n/**\n * Build the initial `DataGridState` for a set of columns. Pass this as the\n * lazy initializer to `useState` — never hand-assemble the state object.\n *\n * ```tsx\n * const [gridState, setGridState] = React.useState(() =>\n * createDefaultDataGridState(columns)\n * );\n * ```\n */\nexport function createDefaultDataGridState(\n columns: readonly DataGridColumnDef<any>[],\n): DataGridState {\n const columnWidths: Record<string, number> = {};\n const columnOrder: string[] = [];\n\n for (const col of columns) {\n columnWidths[col.id] = clampColumnWidth(col, col.width ?? DEFAULT_COL_WIDTH);\n columnOrder.push(col.id);\n }\n\n return {\n sorting: [],\n columnVisibility: {},\n columnWidths,\n columnPinning: { left: [], right: [] },\n columnOrder,\n pagination: { pageIndex: 0, pageSize: 50 },\n selection: { selectedIds: new Set(), anchorId: null },\n dateDisplay: \"relative\",\n quickSearch: \"\",\n };\n}\n\n// ─── Column value resolution ─────────────────────────────────────────\n\nexport function resolveColumnValue<TRow>(\n col: DataGridColumnDef<TRow>,\n row: TRow,\n): unknown {\n if (typeof col.accessor === \"function\") return col.accessor(row);\n const key = (col.accessor ?? col.id) as keyof TRow;\n return row[key];\n}\n\n// ─── Default sort comparator (used by client-mode useDataSource) ────\n\nfunction defaultComparator(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n return stringCompare(String(a), String(b));\n}\n\nexport function buildRowComparator<TRow>(\n sortModel: DataGridSortModel,\n columns: readonly DataGridColumnDef<TRow>[],\n): ((a: TRow, b: TRow) => number) | null {\n if (sortModel.length === 0) return null;\n const colMap = new Map(columns.map((c) => [c.id, c]));\n return (a, b) => {\n for (const { columnId, direction } of sortModel) {\n const col = colMap.get(columnId);\n if (!col) continue;\n const va = resolveColumnValue(col, a);\n const vb = resolveColumnValue(col, b);\n const cmp = col.sortComparator ? col.sortComparator(va, vb) : defaultComparator(va, vb);\n if (cmp !== 0) return direction === \"asc\" ? cmp : -cmp;\n }\n return 0;\n };\n}\n\n// ─── Pagination ──────────────────────────────────────────────────────\n\nexport function paginateRows<TRow>(\n rows: readonly TRow[],\n pagination: DataGridPaginationModel,\n): TRow[] {\n const start = pagination.pageIndex * pagination.pageSize;\n return rows.slice(start, start + pagination.pageSize) as TRow[];\n}\n\n// ─── Quick search ────────────────────────────────────────────────────\n\n/** Default row matcher: case-insensitive substring across every column. */\nexport function defaultMatchRow<TRow>(\n row: TRow,\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n): boolean {\n for (const col of columns) {\n const v = resolveColumnValue(col, row);\n if (v == null) continue;\n if (String(v).toLowerCase().includes(query)) return true;\n }\n return false;\n}\n\nexport function applyQuickSearch<TRow>(\n rows: readonly TRow[],\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n matchRow: (\n row: TRow,\n query: string,\n columns: readonly DataGridColumnDef<TRow>[],\n ) => boolean = defaultMatchRow,\n): readonly TRow[] {\n const trimmed = query.trim().toLowerCase();\n if (!trimmed) return rows;\n return rows.filter((r) => matchRow(r, trimmed, columns));\n}\n\n// ─── Date helpers ────────────────────────────────────────────────────\n\nexport function defaultParseDate(value: unknown): Date | null {\n if (value == null) return null;\n if (value instanceof Date) return isNaN(value.getTime()) ? null : value;\n if (typeof value === \"number\" || typeof value === \"string\") {\n const d = new Date(value);\n return isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\nconst DIVISIONS: Array<{ amount: number; unit: Intl.RelativeTimeFormatUnit }> = [\n { amount: 60, unit: \"second\" },\n { amount: 60, unit: \"minute\" },\n { amount: 24, unit: \"hour\" },\n { amount: 7, unit: \"day\" },\n { amount: 4.34524, unit: \"week\" },\n { amount: 12, unit: \"month\" },\n { amount: Number.POSITIVE_INFINITY, unit: \"year\" },\n];\n\nconst relativeTimeFormatterCache = new Map<string, Intl.RelativeTimeFormat>();\nfunction getRelativeTimeFormatter(locale?: string): Intl.RelativeTimeFormat {\n const key = locale ?? \"__default__\";\n let cached = relativeTimeFormatterCache.get(key);\n if (cached == null) {\n cached = new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" });\n relativeTimeFormatterCache.set(key, cached);\n }\n return cached;\n}\n\nexport function defaultFormatRelative(date: Date): string {\n const rtf = getRelativeTimeFormatter();\n // Wall-clock comparison to \"now\" (e.g. \"5 minutes ago\"). performance.now()\n // would be wrong here — it's a monotonic timer, not a wall-clock instant.\n let duration = (date.getTime() - Date.now()) / 1000;\n for (const div of DIVISIONS) {\n if (Math.abs(duration) < div.amount) return rtf.format(Math.round(duration), div.unit);\n duration /= div.amount;\n }\n return rtf.format(Math.round(duration), \"year\");\n}\n\nexport function defaultFormatAbsolute(date: Date): string {\n return date.toLocaleString();\n}\n\nexport function formatGridDate(\n value: unknown,\n mode: DataGridDateDisplay,\n opts?: {\n parseValue?: (value: unknown) => Date | null;\n dateFormat?: DataGridDateFormat;\n },\n): { display: string | null; tooltip: string | null } {\n const parse = opts?.parseValue ?? defaultParseDate;\n const date = parse(value);\n if (!date) return { display: null, tooltip: null };\n const relative = opts?.dateFormat?.relative ?? defaultFormatRelative;\n const absolute = opts?.dateFormat?.absolute ?? defaultFormatAbsolute;\n const tooltip = absolute(date);\n const display = mode === \"relative\" ? relative(date) : tooltip;\n return { display, tooltip };\n}\n\n// ─── CSV Export ──────────────────────────────────────────────────────\n\nexport function exportToCsv<TRow>(\n rows: readonly TRow[],\n columns: readonly DataGridColumnDef<TRow>[],\n filename: string,\n): void {\n const header = columns.map((col) =>\n typeof col.header === \"string\" ? col.header : col.id,\n );\n const csvRows = rows.map((row) =>\n columns.map((col) => {\n const val = resolveColumnValue(col, row);\n const formatted = col.formatValue\n ? String((col.formatValue(val, row) as string | null | undefined) ?? \"\")\n : String(val ?? \"\");\n if (formatted.includes(\",\") || formatted.includes('\"') || formatted.includes(\"\\n\")) {\n return `\"${formatted.replace(/\"/g, '\"\"')}\"`;\n }\n return formatted;\n }),\n );\n // UTF-8 BOM so Excel opens the CSV as UTF-8.\n const csvContent = \"\\uFEFF\" + [\n header.join(\",\"),\n ...csvRows.map((row) => row.join(\",\")),\n ].join(\"\\n\");\n\n const blob = new Blob([csvContent], { 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 document.body.appendChild(link);\n try {\n link.click();\n } finally {\n link.remove();\n URL.revokeObjectURL(url);\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
react = require_chunk.__toESM(react);
|
|
@@ -30,65 +30,65 @@ const dialogOverlayClasses = new Map([["glassmorphic", "bg-black/50 backdrop-blu
|
|
|
30
30
|
function DesignDialog({ trigger, size = "lg", variant = "glassmorphic", icon: Icon = null, title, description, headerContent, customHeader, footer, noBodyPadding = false, hideTopCloseButton = false, className, overlayClassName, headerClassName, bodyClassName, footerClassName, children, ...dialogRootProps }) {
|
|
31
31
|
const resolvedSizeClass = dialogSizeClasses.get(size) ?? "max-w-lg";
|
|
32
32
|
const resolvedSurfaceClass = dialogSurfaceClasses.get(variant) ?? dialogSurfaceClasses.get("glassmorphic");
|
|
33
|
-
const resolvedOverlayClass = (0,
|
|
33
|
+
const resolvedOverlayClass = (0, _hexclave_ui.cn)(dialogOverlayClasses.get(variant), overlayClassName);
|
|
34
34
|
const shouldRenderTopHeaderRow = Icon != null || title != null || description != null;
|
|
35
35
|
const shouldRenderHeader = customHeader != null || shouldRenderTopHeaderRow || headerContent != null;
|
|
36
36
|
const shouldRenderBody = react.default.Children.toArray(children).filter(Boolean).length > 0;
|
|
37
37
|
const needsAccessibleTitleFallback = !(title != null) && customHeader == null;
|
|
38
38
|
if (process.env.NODE_ENV !== "production" && needsAccessibleTitleFallback) console.warn("[DesignDialog] Rendered without a `title` or `customHeader`. Every dialog needs an accessible name — pass `title`, or render a `DialogTitle` inside `customHeader`.");
|
|
39
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
39
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_hexclave_ui.Dialog, {
|
|
40
40
|
...dialogRootProps,
|
|
41
|
-
children: [trigger != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
41
|
+
children: [trigger != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogTrigger, {
|
|
42
42
|
asChild: true,
|
|
43
43
|
children: trigger
|
|
44
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
45
|
-
className: (0,
|
|
44
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_hexclave_ui.DialogContent, {
|
|
45
|
+
className: (0, _hexclave_ui.cn)("gap-0 p-0 overflow-hidden", resolvedSizeClass, resolvedSurfaceClass, className),
|
|
46
46
|
overlayProps: resolvedOverlayClass ? { className: resolvedOverlayClass } : void 0,
|
|
47
47
|
noCloseButton: hideTopCloseButton,
|
|
48
48
|
children: [
|
|
49
|
-
needsAccessibleTitleFallback && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
49
|
+
needsAccessibleTitleFallback && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogTitle, {
|
|
50
50
|
className: "sr-only",
|
|
51
51
|
children: "Dialog"
|
|
52
52
|
}),
|
|
53
|
-
shouldRenderHeader && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
54
|
-
className: (0,
|
|
53
|
+
shouldRenderHeader && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogHeader, {
|
|
54
|
+
className: (0, _hexclave_ui.cn)("px-6 pt-6 pb-4 border-b border-foreground/[0.06]", headerClassName),
|
|
55
55
|
children: customHeader ?? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [shouldRenderTopHeaderRow && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
56
|
-
className: (0,
|
|
56
|
+
className: (0, _hexclave_ui.cn)("flex items-start gap-3", Icon == null && "gap-0"),
|
|
57
57
|
children: [Icon != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
58
58
|
className: "h-9 w-9 rounded-xl bg-primary/10 ring-1 ring-primary/15 flex items-center justify-center shrink-0",
|
|
59
59
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4 text-primary" })
|
|
60
60
|
}), (title != null || description != null) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
61
61
|
className: "flex-1 min-w-0 space-y-1",
|
|
62
|
-
children: [title != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
62
|
+
children: [title != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogTitle, {
|
|
63
63
|
className: "text-base",
|
|
64
64
|
children: title
|
|
65
|
-
}) : null, description != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
65
|
+
}) : null, description != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogDescription, {
|
|
66
66
|
className: "text-xs",
|
|
67
67
|
children: description
|
|
68
68
|
}) : null]
|
|
69
69
|
})]
|
|
70
70
|
}), headerContent != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
71
|
-
className: (0,
|
|
71
|
+
className: (0, _hexclave_ui.cn)(shouldRenderTopHeaderRow && "mt-4"),
|
|
72
72
|
children: headerContent
|
|
73
73
|
}) : null] })
|
|
74
74
|
}),
|
|
75
|
-
shouldRenderBody && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
76
|
-
className: (0,
|
|
75
|
+
shouldRenderBody && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogBody, {
|
|
76
|
+
className: (0, _hexclave_ui.cn)("mx-0 my-0 w-auto", noBodyPadding ? "px-0 py-0" : "px-6 py-4", bodyClassName),
|
|
77
77
|
children
|
|
78
78
|
}),
|
|
79
|
-
footer != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
80
|
-
className: (0,
|
|
79
|
+
footer != null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.DialogFooter, {
|
|
80
|
+
className: (0, _hexclave_ui.cn)("px-6 py-3 border-t border-foreground/[0.06] bg-foreground/[0.02]", footerClassName),
|
|
81
81
|
children: footer
|
|
82
82
|
}) : null
|
|
83
83
|
]
|
|
84
84
|
})]
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
-
const DesignDialogRoot =
|
|
88
|
-
const DesignDialogTrigger =
|
|
89
|
-
const DesignDialogClose =
|
|
90
|
-
const DesignDialogTitle =
|
|
91
|
-
const DesignDialogDescription =
|
|
87
|
+
const DesignDialogRoot = _hexclave_ui.Dialog;
|
|
88
|
+
const DesignDialogTrigger = _hexclave_ui.DialogTrigger;
|
|
89
|
+
const DesignDialogClose = _hexclave_ui.DialogClose;
|
|
90
|
+
const DesignDialogTitle = _hexclave_ui.DialogTitle;
|
|
91
|
+
const DesignDialogDescription = _hexclave_ui.DialogDescription;
|
|
92
92
|
|
|
93
93
|
//#endregion
|
|
94
94
|
exports.DesignDialog = DesignDialog;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":["React","Dialog","DialogTrigger","DialogContent","DialogTitle","DialogHeader","DialogDescription","DialogBody","DialogFooter","DialogClose"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n cn,\n} from \"@
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["React","Dialog","DialogTrigger","DialogContent","DialogTitle","DialogHeader","DialogDescription","DialogBody","DialogFooter","DialogClose"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n cn,\n} from \"@hexclave/ui\";\nimport React from \"react\";\n\nexport type DesignDialogSize =\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\"\n | \"5xl\"\n | \"6xl\"\n | \"7xl\"\n | \"full\";\n\nexport type DesignDialogVariant = \"glassmorphic\" | \"plain\";\n\nconst dialogSizeClasses = new Map<DesignDialogSize, string>([\n [\"sm\", \"max-w-sm\"],\n [\"md\", \"max-w-md\"],\n [\"lg\", \"max-w-lg\"],\n [\"xl\", \"max-w-xl\"],\n [\"2xl\", \"max-w-2xl\"],\n [\"3xl\", \"max-w-3xl\"],\n [\"4xl\", \"max-w-4xl\"],\n [\"5xl\", \"max-w-5xl\"],\n [\"6xl\", \"max-w-6xl\"],\n [\"7xl\", \"max-w-7xl\"],\n [\"full\", \"max-w-[calc(100vw-2rem)]\"],\n]);\n\nconst dialogSurfaceClasses = new Map<DesignDialogVariant, string>([\n [\"glassmorphic\", \"border-0 sm:rounded-2xl bg-background/85 backdrop-blur-2xl ring-1 ring-foreground/[0.06] shadow-[0_24px_48px_-12px_rgba(0,0,0,0.25),0_4px_24px_-8px_rgba(0,0,0,0.12)] dark:bg-background/80 dark:ring-white/[0.06]\"],\n [\"plain\", \"border bg-background shadow-lg sm:rounded-lg\"],\n]);\n\nconst dialogOverlayClasses = new Map<DesignDialogVariant, string | undefined>([\n [\"glassmorphic\", \"bg-black/50 backdrop-blur-sm\"],\n [\"plain\", undefined],\n]);\n\ntype DesignDialogIcon = React.ElementType<{ className?: string }>;\n\ntype DesignDialogRootProps = Omit<React.ComponentProps<typeof Dialog>, \"children\">;\n\nexport type DesignDialogProps = {\n trigger?: React.ReactElement,\n size?: DesignDialogSize,\n variant?: DesignDialogVariant,\n icon?: DesignDialogIcon | null,\n title?: React.ReactNode,\n description?: React.ReactNode,\n headerContent?: React.ReactNode,\n customHeader?: React.ReactNode,\n footer?: React.ReactNode,\n noBodyPadding?: boolean,\n hideTopCloseButton?: boolean,\n className?: string,\n overlayClassName?: string,\n headerClassName?: string,\n bodyClassName?: string,\n footerClassName?: string,\n children?: React.ReactNode,\n} & DesignDialogRootProps;\n\n/**\n * Canonical dashboard modal surface. This wraps the base dialog primitives with\n * a reusable glassmorphic shell and consistent header/body/footer regions.\n */\nexport function DesignDialog({\n trigger,\n size = \"lg\",\n variant = \"glassmorphic\",\n icon: Icon = null,\n title,\n description,\n headerContent,\n customHeader,\n footer,\n noBodyPadding = false,\n hideTopCloseButton = false,\n className,\n overlayClassName,\n headerClassName,\n bodyClassName,\n footerClassName,\n children,\n ...dialogRootProps\n}: DesignDialogProps) {\n const resolvedSizeClass = dialogSizeClasses.get(size) ?? \"max-w-lg\";\n const resolvedSurfaceClass = dialogSurfaceClasses.get(variant) ?? dialogSurfaceClasses.get(\"glassmorphic\");\n const resolvedOverlayClass = cn(dialogOverlayClasses.get(variant), overlayClassName);\n const shouldRenderTopHeaderRow = Icon != null || title != null || description != null;\n const shouldRenderHeader = customHeader != null || shouldRenderTopHeaderRow || headerContent != null;\n // Use toArray + filter(Boolean) instead of Children.count so that\n // expressions like `{condition && <Foo/>}` resolving to `false` don't\n // produce an empty DialogBody (which would still render padding/borders).\n const shouldRenderBody = React.Children.toArray(children).filter(Boolean).length > 0;\n const hasStandardTitle = title != null;\n const needsAccessibleTitleFallback = !hasStandardTitle && customHeader == null;\n\n if (process.env.NODE_ENV !== \"production\" && needsAccessibleTitleFallback) {\n console.warn(\n \"[DesignDialog] Rendered without a `title` or `customHeader`. Every dialog needs an accessible name — pass `title`, or render a `DialogTitle` inside `customHeader`.\",\n );\n }\n\n return (\n <Dialog {...dialogRootProps}>\n {trigger != null && (\n <DialogTrigger asChild>\n {trigger}\n </DialogTrigger>\n )}\n\n <DialogContent\n className={cn(\n \"gap-0 p-0 overflow-hidden\",\n resolvedSizeClass,\n resolvedSurfaceClass,\n className\n )}\n overlayProps={resolvedOverlayClass ? { className: resolvedOverlayClass } : undefined}\n noCloseButton={hideTopCloseButton}\n >\n {needsAccessibleTitleFallback && (\n <DialogTitle className=\"sr-only\">Dialog</DialogTitle>\n )}\n {shouldRenderHeader && (\n <DialogHeader className={cn(\"px-6 pt-6 pb-4 border-b border-foreground/[0.06]\", headerClassName)}>\n {customHeader ?? (\n <>\n {shouldRenderTopHeaderRow && (\n <div className={cn(\"flex items-start gap-3\", Icon == null && \"gap-0\")}>\n {Icon != null && (\n <div className=\"h-9 w-9 rounded-xl bg-primary/10 ring-1 ring-primary/15 flex items-center justify-center shrink-0\">\n <Icon className=\"h-4 w-4 text-primary\" />\n </div>\n )}\n {(title != null || description != null) && (\n <div className=\"flex-1 min-w-0 space-y-1\">\n {title != null ? (\n <DialogTitle className=\"text-base\">\n {title}\n </DialogTitle>\n ) : null}\n {description != null ? (\n <DialogDescription className=\"text-xs\">\n {description}\n </DialogDescription>\n ) : null}\n </div>\n )}\n </div>\n )}\n\n {headerContent != null ? (\n <div className={cn(shouldRenderTopHeaderRow && \"mt-4\")}>\n {headerContent}\n </div>\n ) : null}\n </>\n )}\n </DialogHeader>\n )}\n\n {shouldRenderBody && (\n <DialogBody\n className={cn(\n \"mx-0 my-0 w-auto\",\n noBodyPadding ? \"px-0 py-0\" : \"px-6 py-4\",\n bodyClassName\n )}\n >\n {children}\n </DialogBody>\n )}\n\n {footer != null ? (\n <DialogFooter className={cn(\"px-6 py-3 border-t border-foreground/[0.06] bg-foreground/[0.02]\", footerClassName)}>\n {footer}\n </DialogFooter>\n ) : null}\n </DialogContent>\n </Dialog>\n );\n}\n\nexport const DesignDialogRoot = Dialog;\nexport const DesignDialogTrigger = DialogTrigger;\nexport const DesignDialogClose = DialogClose;\nexport const DesignDialogTitle = DialogTitle;\nexport const DesignDialogDescription = DialogDescription;\n"],"mappings":";;;;;;;;;;AA+BA,MAAM,oBAAoB,IAAI,IAA8B;CAC1D,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,QAAQ,2BAA2B;CACrC,CAAC;AAEF,MAAM,uBAAuB,IAAI,IAAiC,CAChE,CAAC,gBAAgB,qNAAqN,EACtO,CAAC,SAAS,+CAA+C,CAC1D,CAAC;AAEF,MAAM,uBAAuB,IAAI,IAA6C,CAC5E,CAAC,gBAAgB,+BAA+B,EAChD,CAAC,SAAS,OAAU,CACrB,CAAC;;;;;AA8BF,SAAgB,aAAa,EAC3B,SACA,OAAO,MACP,UAAU,gBACV,MAAM,OAAO,MACb,OACA,aACA,eACA,cACA,QACA,gBAAgB,OAChB,qBAAqB,OACrB,WACA,kBACA,iBACA,eACA,iBACA,UACA,GAAG,mBACiB;CACpB,MAAM,oBAAoB,kBAAkB,IAAI,KAAK,IAAI;CACzD,MAAM,uBAAuB,qBAAqB,IAAI,QAAQ,IAAI,qBAAqB,IAAI,eAAe;CAC1G,MAAM,4CAA0B,qBAAqB,IAAI,QAAQ,EAAE,iBAAiB;CACpF,MAAM,2BAA2B,QAAQ,QAAQ,SAAS,QAAQ,eAAe;CACjF,MAAM,qBAAqB,gBAAgB,QAAQ,4BAA4B,iBAAiB;CAIhG,MAAM,mBAAmBA,cAAM,SAAS,QAAQ,SAAS,CAAC,OAAO,QAAQ,CAAC,SAAS;CAEnF,MAAM,+BAA+B,EADZ,SAAS,SACwB,gBAAgB;AAE1E,KAAI,QAAQ,IAAI,aAAa,gBAAgB,6BAC3C,SAAQ,KACN,sKACD;AAGH,QACE,4CAACC;EAAO,GAAI;aACT,WAAW,QACV,2CAACC;GAAc;aACZ;IACa,EAGlB,4CAACC;GACC,gCACE,6BACA,mBACA,sBACA,UACD;GACD,cAAc,uBAAuB,EAAE,WAAW,sBAAsB,GAAG;GAC3E,eAAe;;IAEd,gCACC,2CAACC;KAAY,WAAU;eAAU;MAAoB;IAEtD,sBACC,2CAACC;KAAa,gCAAc,oDAAoD,gBAAgB;eAC7F,gBACC,qFACG,4BACC,4CAAC;MAAI,gCAAc,0BAA0B,QAAQ,QAAQ,QAAQ;iBAClE,QAAQ,QACP,2CAAC;OAAI,WAAU;iBACb,2CAAC,QAAK,WAAU,yBAAyB;QACrC,GAEN,SAAS,QAAQ,eAAe,SAChC,4CAAC;OAAI,WAAU;kBACZ,SAAS,OACR,2CAACD;QAAY,WAAU;kBACpB;SACW,GACZ,MACH,eAAe,OACd,2CAACE;QAAkB,WAAU;kBAC1B;SACiB,GAClB;QACA;OAEJ,EAGP,iBAAiB,OAChB,2CAAC;MAAI,gCAAc,4BAA4B,OAAO;gBACnD;OACG,GACJ,QACH;MAEQ;IAGhB,oBACC,2CAACC;KACC,gCACE,oBACA,gBAAgB,cAAc,aAC9B,cACD;KAEA;MACU;IAGd,UAAU,OACT,2CAACC;KAAa,gCAAc,oEAAoE,gBAAgB;eAC7G;MACY,GACb;;IACU;GACT;;AAIb,MAAa,mBAAmBP;AAChC,MAAa,sBAAsBC;AACnC,MAAa,oBAAoBO;AACjC,MAAa,oBAAoBL;AACjC,MAAa,0BAA0BE"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
react = require_chunk.__toESM(react);
|
|
@@ -26,7 +26,7 @@ react = require_chunk.__toESM(react);
|
|
|
26
26
|
*/
|
|
27
27
|
function DesignEmptyState({ icon: Icon, title = "No data available", description, children, className }) {
|
|
28
28
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29
|
-
className: (0,
|
|
29
|
+
className: (0, _hexclave_ui.cn)("flex flex-col items-center justify-center py-12 px-6 text-center", className),
|
|
30
30
|
children: [
|
|
31
31
|
Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
32
32
|
className: "mb-4",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@
|
|
1
|
+
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@hexclave/ui\";\nimport React from \"react\";\n\nexport type DesignEmptyStateProps = {\n icon?: React.ElementType,\n title?: string,\n description?: string,\n children?: React.ReactNode,\n className?: string,\n};\n\n/**\n * Centered \"no data\" placeholder. Show this inside a `DataGrid` via the\n * `emptyState` prop, inside a chart when a query returns zero rows, or\n * inside a card when a section has nothing to display.\n *\n * ```tsx\n * <DesignEmptyState\n * icon={SearchIcon}\n * title=\"No results\"\n * description=\"Try adjusting your filters.\"\n * />\n * ```\n *\n * Prefer this over a raw \"No data\" div — it handles spacing, typography,\n * and the optional icon for you. `icon` is a component type, not a rendered node.\n */\nexport function DesignEmptyState({\n icon: Icon,\n title = \"No data available\",\n description,\n children,\n className,\n}: DesignEmptyStateProps) {\n return (\n <div\n className={cn(\n \"flex flex-col items-center justify-center py-12 px-6 text-center\",\n className\n )}\n >\n {Icon && (\n <div className=\"mb-4\">\n <Icon className=\"h-10 w-10 text-muted-foreground/30\" />\n </div>\n )}\n <h3 className=\"text-sm font-medium text-foreground\">\n {title}\n </h3>\n {description && (\n <p className=\"mt-1 text-xs text-muted-foreground max-w-[280px]\">\n {description}\n </p>\n )}\n {children && (\n <div className=\"mt-4\">\n {children}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,iBAAiB,EAC/B,MAAM,MACN,QAAQ,qBACR,aACA,UACA,aACwB;AACxB,QACE,4CAAC;EACC,gCACE,oEACA,UACD;;GAEA,QACC,2CAAC;IAAI,WAAU;cACb,2CAAC,QAAK,WAAU,uCAAuC;KACnD;GAER,2CAAC;IAAG,WAAU;cACX;KACE;GACJ,eACC,2CAAC;IAAE,WAAU;cACV;KACC;GAEL,YACC,2CAAC;IAAI,WAAU;IACZ;KACG;;GAEJ"}
|
package/dist/components/input.js
CHANGED
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let
|
|
7
|
+
let _hexclave_shared_dist_utils_react = require("@hexclave/shared/dist/utils/react");
|
|
8
8
|
let react = require("react");
|
|
9
9
|
react = require_chunk.__toESM(react);
|
|
10
10
|
|
|
11
11
|
//#region src/components/input.tsx
|
|
12
|
-
const DesignInput = (0,
|
|
12
|
+
const DesignInput = (0, _hexclave_shared_dist_utils_react.forwardRefIfNeeded)(({ className, type, prefixItem, leadingIcon, size = "md", ...props }, ref) => {
|
|
13
13
|
const sizeClasses = size === "sm" ? "h-7 px-2 text-xs" : size === "lg" ? "h-10 px-4 text-sm" : "h-9 px-3 text-sm";
|
|
14
|
-
const baseClasses = (0,
|
|
14
|
+
const baseClasses = (0, _hexclave_ui.cn)("stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]", "disabled:cursor-not-allowed disabled:opacity-50", "transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]", sizeClasses);
|
|
15
15
|
if (prefixItem) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16
16
|
className: "flex flex-row items-center flex-1 rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06] overflow-hidden transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1]",
|
|
17
17
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
18
|
-
className: (0,
|
|
18
|
+
className: (0, _hexclave_ui.cn)("flex self-stretch items-center justify-center select-none text-muted-foreground/70 border-r border-black/[0.06] dark:border-white/[0.06] bg-black/[0.03] dark:bg-white/[0.02]", size === "sm" ? "px-2.5 text-xs" : size === "lg" ? "px-3.5 text-sm" : "px-3 text-sm"),
|
|
19
19
|
children: prefixItem
|
|
20
20
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
21
21
|
type,
|
|
22
|
-
className: (0,
|
|
22
|
+
className: (0, _hexclave_ui.cn)("stack-scope flex w-full bg-transparent", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none", "disabled:cursor-not-allowed disabled:opacity-50", sizeClasses, "rounded-none border-0 shadow-none ring-0 focus-visible:ring-0", className),
|
|
23
23
|
ref,
|
|
24
24
|
...props
|
|
25
25
|
})]
|
|
@@ -31,7 +31,7 @@ const DesignInput = (0, _stackframe_stack_shared_dist_utils_react.forwardRefIfNe
|
|
|
31
31
|
children: leadingIcon
|
|
32
32
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
33
33
|
type,
|
|
34
|
-
className: (0,
|
|
34
|
+
className: (0, _hexclave_ui.cn)(baseClasses, "pl-8", className),
|
|
35
35
|
ref,
|
|
36
36
|
...props
|
|
37
37
|
})]
|
|
@@ -40,7 +40,7 @@ const DesignInput = (0, _stackframe_stack_shared_dist_utils_react.forwardRefIfNe
|
|
|
40
40
|
className: "flex flex-row items-center flex-1",
|
|
41
41
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
42
42
|
type,
|
|
43
|
-
className: (0,
|
|
43
|
+
className: (0, _hexclave_ui.cn)(baseClasses, className),
|
|
44
44
|
ref,
|
|
45
45
|
...props
|
|
46
46
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRefIfNeeded } from \"@
|
|
1
|
+
{"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRefIfNeeded } from \"@hexclave/shared/dist/utils/react\";\nimport React from \"react\";\n\nimport { cn } from \"@hexclave/ui\";\n\nexport type DesignInputProps = {\n prefixItem?: React.ReactNode,\n leadingIcon?: React.ReactNode,\n size?: \"sm\" | \"md\" | \"lg\",\n} & Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">;\n\nexport const DesignInput = forwardRefIfNeeded<HTMLInputElement, DesignInputProps>(\n ({ className, type, prefixItem, leadingIcon, size = \"md\", ...props }, ref) => {\n const sizeClasses = size === \"sm\"\n ? \"h-7 px-2 text-xs\"\n : size === \"lg\"\n ? \"h-10 px-4 text-sm\"\n : \"h-9 px-3 text-sm\";\n const baseClasses = cn(\n \"stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]\",\n sizeClasses\n );\n\n if (prefixItem) {\n return (\n <div className=\"flex flex-row items-center flex-1 rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06] overflow-hidden transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1]\">\n <div className={cn(\n \"flex self-stretch items-center justify-center select-none text-muted-foreground/70 border-r border-black/[0.06] dark:border-white/[0.06] bg-black/[0.03] dark:bg-white/[0.02]\",\n size === \"sm\" ? \"px-2.5 text-xs\" : size === \"lg\" ? \"px-3.5 text-sm\" : \"px-3 text-sm\"\n )}>\n {prefixItem}\n </div>\n <input\n type={type}\n className={cn(\n \"stack-scope flex w-full bg-transparent\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n sizeClasses,\n \"rounded-none border-0 shadow-none ring-0 focus-visible:ring-0\",\n className\n )}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n if (leadingIcon) {\n return (\n <div className=\"relative flex flex-row items-center flex-1\">\n <div className=\"pointer-events-none absolute left-2.5 flex items-center text-muted-foreground\">\n {leadingIcon}\n </div>\n <input\n type={type}\n className={cn(baseClasses, \"pl-8\", className)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-row items-center flex-1\">\n <input\n type={type}\n className={cn(baseClasses, className)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n);\nDesignInput.displayName = \"DesignInput\";\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,yEACV,EAAE,WAAW,MAAM,YAAY,aAAa,OAAO,MAAM,GAAG,SAAS,QAAQ;CAC5E,MAAM,cAAc,SAAS,OACzB,qBACA,SAAS,OACP,sBACA;CACN,MAAM,mCACJ,0LACA,mEACA,4HACA,mDACA,oGACA,YACD;AAED,KAAI,WACF,QACE,4CAAC;EAAI,WAAU;aACb,2CAAC;GAAI,gCACH,iLACA,SAAS,OAAO,mBAAmB,SAAS,OAAO,mBAAmB,eACvE;aACE;IACG,EACN,2CAAC;GACO;GACN,gCACE,0CACA,mEACA,mEACA,mDACA,aACA,iEACA,UACD;GACI;GACL,GAAI;IACJ;GACE;AAIV,KAAI,YACF,QACE,4CAAC;EAAI,WAAU;aACb,2CAAC;GAAI,WAAU;aACZ;IACG,EACN,2CAAC;GACO;GACN,gCAAc,aAAa,QAAQ,UAAU;GACxC;GACL,GAAI;IACJ;GACE;AAIV,QACE,2CAAC;EAAI,WAAU;YACb,2CAAC;GACO;GACN,gCAAc,aAAa,UAAU;GAChC;GACL,GAAI;IACJ;GACE;EAGX;AACD,YAAY,cAAc"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
react = require_chunk.__toESM(react);
|
|
@@ -43,11 +43,11 @@ const hoverTintClasses = new Map([
|
|
|
43
43
|
function DesignMetricCard({ label, value, description, trend, icon: Icon, gradient = "default", className, ...props }) {
|
|
44
44
|
const hoverTintClass = hoverTintClasses.get(gradient) ?? "group-hover:bg-slate-500/[0.02]";
|
|
45
45
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
46
|
-
className: (0,
|
|
46
|
+
className: (0, _hexclave_ui.cn)("group relative rounded-2xl bg-white/90 dark:bg-background/60 backdrop-blur-xl transition-all duration-150 hover:transition-none overflow-hidden", "ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]", "shadow-sm hover:shadow-md", className),
|
|
47
47
|
...props,
|
|
48
48
|
children: [
|
|
49
49
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl" }),
|
|
50
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0,
|
|
50
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0, _hexclave_ui.cn)("absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl", hoverTintClass) }),
|
|
51
51
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
52
52
|
className: "relative p-5",
|
|
53
53
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -71,10 +71,10 @@ function DesignMetricCard({ label, value, description, trend, icon: Icon, gradie
|
|
|
71
71
|
className: "text-3xl font-bold tabular-nums text-foreground",
|
|
72
72
|
children: typeof value === "number" ? value.toLocaleString() : value
|
|
73
73
|
}), trend && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
74
|
-
className: (0,
|
|
74
|
+
className: (0, _hexclave_ui.cn)("inline-flex items-center gap-0.5 text-xs font-medium", trend.direction === "up" ? "text-emerald-600 dark:text-emerald-400" : "text-red-600 dark:text-red-400"),
|
|
75
75
|
children: [
|
|
76
76
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
77
|
-
className: (0,
|
|
77
|
+
className: (0, _hexclave_ui.cn)("h-3 w-3", trend.direction === "down" && "rotate-180"),
|
|
78
78
|
viewBox: "0 0 12 12",
|
|
79
79
|
fill: "none",
|
|
80
80
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metric-card.js","names":[],"sources":["../../src/components/metric-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@
|
|
1
|
+
{"version":3,"file":"metric-card.js","names":[],"sources":["../../src/components/metric-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@hexclave/ui\";\nimport React from \"react\";\n\ntype DesignMetricCardGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst hoverTintClasses = new Map<DesignMetricCardGradient, string>([\n [\"blue\", \"group-hover:bg-blue-500/[0.03]\"],\n [\"cyan\", \"group-hover:bg-cyan-500/[0.03]\"],\n [\"purple\", \"group-hover:bg-purple-500/[0.03]\"],\n [\"green\", \"group-hover:bg-emerald-500/[0.03]\"],\n [\"orange\", \"group-hover:bg-orange-500/[0.03]\"],\n [\"default\", \"group-hover:bg-slate-500/[0.02]\"],\n]);\n\nexport type DesignMetricCardTrend = {\n value: number,\n direction: \"up\" | \"down\",\n label?: string,\n};\n\nexport type DesignMetricCardProps = {\n label: string,\n value: string | number,\n description?: string,\n trend?: DesignMetricCardTrend,\n icon?: React.ElementType,\n gradient?: DesignMetricCardGradient,\n} & Omit<React.ComponentProps<\"div\">, \"children\">;\n\n/**\n * KPI card for big-number metrics (users, revenue, signups, etc.).\n * Use this instead of a plain `DesignCard` when the value is the focal point.\n *\n * ```tsx\n * <DesignMetricCard\n * label=\"Total Users\"\n * value=\"1,234\"\n * description=\"+12% from last month\"\n * trend={{ direction: \"up\", value: 12, label: \"vs. last period\" }}\n * icon={UsersIcon}\n * gradient=\"blue\"\n * />\n * ```\n *\n * Notes:\n * - `label` is the short caption (NOT `title`).\n * - `value` can be a pre-formatted string (\"1,234\") or a number — prefer\n * strings so you control the format.\n * - `description` is the subline (NOT `subtitle`).\n * - `trend.value` is a NUMBER, not a pre-formatted \"12%\" string. The card\n * renders the arrow and formatting.\n * - `icon` is a component type (e.g. `UsersIcon`), not a rendered node.\n */\nexport function DesignMetricCard({\n label,\n value,\n description,\n trend,\n icon: Icon,\n gradient = \"default\",\n className,\n ...props\n}: DesignMetricCardProps) {\n const hoverTintClass = hoverTintClasses.get(gradient) ?? \"group-hover:bg-slate-500/[0.02]\";\n\n return (\n <div\n className={cn(\n \"group relative rounded-2xl bg-white/90 dark:bg-background/60 backdrop-blur-xl transition-all duration-150 hover:transition-none overflow-hidden\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-sm hover:shadow-md\",\n className\n )}\n {...props}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl\" />\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl\",\n hoverTintClass\n )}\n />\n <div className=\"relative p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {Icon && (\n <div className=\"p-1.5 rounded-lg bg-foreground/[0.06] dark:bg-foreground/[0.04]\">\n <Icon className=\"h-3.5 w-3.5 text-foreground/70 dark:text-muted-foreground\" />\n </div>\n )}\n <span className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wider\">\n {label}\n </span>\n </div>\n <div className=\"mt-3 flex items-baseline gap-2\">\n <span className=\"text-3xl font-bold tabular-nums text-foreground\">\n {typeof value === \"number\" ? value.toLocaleString() : value}\n </span>\n {trend && (\n <span\n className={cn(\n \"inline-flex items-center gap-0.5 text-xs font-medium\",\n trend.direction === \"up\"\n ? \"text-emerald-600 dark:text-emerald-400\"\n : \"text-red-600 dark:text-red-400\"\n )}\n >\n <svg\n className={cn(\"h-3 w-3\", trend.direction === \"down\" && \"rotate-180\")}\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 2.5V9.5M6 2.5L3 5.5M6 2.5L9 5.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n {trend.value}%\n {trend.label && (\n <span className=\"text-muted-foreground ml-0.5\">{trend.label}</span>\n )}\n </span>\n )}\n </div>\n {description && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {description}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAOA,MAAM,mBAAmB,IAAI,IAAsC;CACjE,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,oCAAoC;CAC9C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,WAAW,kCAAkC;CAC/C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AAyCF,SAAgB,iBAAiB,EAC/B,OACA,OACA,aACA,OACA,MAAM,MACN,WAAW,WACX,WACA,GAAG,SACqB;CACxB,MAAM,iBAAiB,iBAAiB,IAAI,SAAS,IAAI;AAEzD,QACE,4CAAC;EACC,gCACE,mJACA,sGACA,6BACA,UACD;EACD,GAAI;;GAEJ,2CAAC,SAAI,WAAU,yIAAyI;GACxJ,2CAAC,SACC,gCACE,+GACA,eACD,GACD;GACF,2CAAC;IAAI,WAAU;cACb,2CAAC;KAAI,WAAU;eACb,4CAAC;MAAI,WAAU;;OACb,4CAAC;QAAI,WAAU;mBACZ,QACC,2CAAC;SAAI,WAAU;mBACb,2CAAC,QAAK,WAAU,8DAA8D;UAC1E,EAER,2CAAC;SAAK,WAAU;mBACb;UACI;SACH;OACN,4CAAC;QAAI,WAAU;mBACb,2CAAC;SAAK,WAAU;mBACb,OAAO,UAAU,WAAW,MAAM,gBAAgB,GAAG;UACjD,EACN,SACC,4CAAC;SACC,gCACE,wDACA,MAAM,cAAc,OAChB,2CACA,iCACL;;UAED,2CAAC;WACC,gCAAc,WAAW,MAAM,cAAc,UAAU,aAAa;WACpE,SAAQ;WACR,MAAK;WACL,OAAM;qBAEN,2CAAC;YACC,GAAE;YACF,QAAO;YACP,aAAY;YACZ,eAAc;YACd,gBAAe;aACf;YACE;UACL,MAAM;UAAM;UACZ,MAAM,SACL,2CAAC;WAAK,WAAU;qBAAgC,MAAM;YAAa;;UAEhE;SAEL;OACL,eACC,2CAAC;QAAE,WAAU;kBACV;SACC;;OAEF;MACF;KACF;;GACF"}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react = require("react");
|
|
8
|
-
let
|
|
8
|
+
let _hexclave_shared_dist_utils_promises = require("@hexclave/shared/dist/utils/promises");
|
|
9
9
|
let _radix_ui_react_tooltip = require("@radix-ui/react-tooltip");
|
|
10
10
|
let __card_js = require("./card.js");
|
|
11
11
|
|
|
@@ -46,32 +46,33 @@ function DesignPillToggle({ options, selected, onSelect, size = "md", glassmorph
|
|
|
46
46
|
const result = onSelect(optionId);
|
|
47
47
|
if (result && typeof result.then === "function") {
|
|
48
48
|
setLoadingOptionId(optionId);
|
|
49
|
-
(0,
|
|
49
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronouslyWithAlert)(Promise.resolve(result).finally(() => setLoadingOptionId(null)));
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
53
|
-
className: (0,
|
|
53
|
+
className: (0, _hexclave_ui.cn)("inline-flex items-center gap-1 p-1 rounded-xl", glassmorphic ? "bg-foreground/[0.04] backdrop-blur-sm" : "bg-black/[0.08] dark:bg-white/[0.04]", className),
|
|
54
54
|
children: options.map((option) => {
|
|
55
55
|
const isActive = selected === option.id;
|
|
56
56
|
const Icon = option.icon;
|
|
57
57
|
const pill = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
58
|
+
type: "button",
|
|
58
59
|
onClick: () => handleClick(option.id),
|
|
59
60
|
disabled: loadingOptionId !== null,
|
|
60
|
-
className: (0,
|
|
61
|
-
children: [loadingOptionId === option.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
61
|
+
className: (0, _hexclave_ui.cn)("relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none", sizeClass.button, isActive ? (0, _hexclave_ui.cn)("bg-background text-foreground shadow-sm ring-1", glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass) : (0, _hexclave_ui.cn)("text-muted-foreground hover:text-foreground", glassmorphic ? "hover:bg-background/50" : "hover:bg-black/[0.06] dark:hover:bg-white/[0.04]")),
|
|
62
|
+
children: [loadingOptionId === option.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.Spinner, {
|
|
62
63
|
size: 12,
|
|
63
64
|
className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none"
|
|
64
65
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
65
|
-
className: (0,
|
|
66
|
+
className: (0, _hexclave_ui.cn)("flex items-center gap-2", loadingOptionId === option.id && "invisible"),
|
|
66
67
|
children: [Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: sizeClass.icon }), showLabels && option.label]
|
|
67
68
|
})]
|
|
68
69
|
}, option.id);
|
|
69
|
-
if (!showLabels) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
70
|
+
if (!showLabels) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_hexclave_ui.Tooltip, {
|
|
70
71
|
delayDuration: 0,
|
|
71
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
72
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.TooltipTrigger, {
|
|
72
73
|
asChild: true,
|
|
73
74
|
children: pill
|
|
74
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.TooltipPortal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
75
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.TooltipPortal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.TooltipContent, {
|
|
75
76
|
side: "top",
|
|
76
77
|
children: option.label
|
|
77
78
|
}) })]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pill-toggle.js","names":["Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent"],"sources":["../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipTrigger } from \"@
|
|
1
|
+
{"version":3,"file":"pill-toggle.js","names":["Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent"],"sources":["../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipTrigger } from \"@hexclave/ui\";\nimport { TooltipPortal } from \"@radix-ui/react-tooltip\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { useGlassmorphicDefault } from \"./card\";\n\ntype DesignPillToggleSize = \"sm\" | \"md\" | \"lg\";\ntype DesignPillToggleGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nexport type DesignPillToggleOption = {\n id: string,\n label: string,\n icon?: React.ElementType,\n};\n\nexport type DesignPillToggleProps = {\n options: DesignPillToggleOption[],\n selected: string,\n onSelect: (id: string) => void | Promise<void>,\n size?: DesignPillToggleSize,\n glassmorphic?: boolean,\n gradient?: DesignPillToggleGradient,\n /** When false, hides labels and shows a tooltip on hover instead. Defaults to true. */\n showLabels?: boolean,\n className?: string,\n};\n\ntype SizeClass = {\n button: string,\n icon: string,\n};\n\nconst sizeClasses = new Map<DesignPillToggleSize, SizeClass>([\n [\"sm\", { button: \"px-3 py-1.5 text-xs\", icon: \"h-3.5 w-3.5\" }],\n [\"md\", { button: \"px-4 py-2 text-sm\", icon: \"h-4 w-4\" }],\n [\"lg\", { button: \"px-5 py-2.5 text-sm\", icon: \"h-4 w-4\" }],\n]);\n\nconst gradientClasses = new Map<DesignPillToggleGradient, string>([\n [\"blue\", \"ring-blue-500/20 dark:ring-blue-400/20\"],\n [\"cyan\", \"ring-cyan-500/20 dark:ring-cyan-400/20\"],\n [\"purple\", \"ring-purple-500/20 dark:ring-purple-400/20\"],\n [\"green\", \"ring-emerald-500/20 dark:ring-emerald-400/20\"],\n [\"orange\", \"ring-amber-500/20 dark:ring-amber-400/20\"],\n [\"default\", \"ring-black/[0.12] dark:ring-white/[0.06]\"],\n]);\n\nfunction getMapValueOrThrow<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, mapName: string) {\n const value = map.get(key);\n if (!value) {\n throw new Error(`Missing ${mapName} entry for key \"${String(key)}\"`);\n }\n return value;\n}\n\nexport function DesignPillToggle({\n options,\n selected,\n onSelect,\n size = \"md\",\n glassmorphic: glassmorphicProp,\n gradient = \"default\",\n showLabels = true,\n className,\n}: DesignPillToggleProps) {\n const glassmorphic = useGlassmorphicDefault(glassmorphicProp);\n const sizeClass = getMapValueOrThrow(sizeClasses, size, \"sizeClasses\");\n const activeRingClass = getMapValueOrThrow(gradientClasses, gradient, \"gradientClasses\");\n\n const [loadingOptionId, setLoadingOptionId] = useState<string | null>(null);\n\n const handleClick = (optionId: string) => {\n const result = onSelect(optionId);\n if (result && typeof (result as Promise<void>).then === \"function\") {\n setLoadingOptionId(optionId);\n runAsynchronouslyWithAlert(\n Promise.resolve(result).finally(() => setLoadingOptionId(null))\n );\n }\n };\n\n return (\n <div\n className={cn(\n \"inline-flex items-center gap-1 p-1 rounded-xl\",\n glassmorphic\n ? \"bg-foreground/[0.04] backdrop-blur-sm\"\n : \"bg-black/[0.08] dark:bg-white/[0.04]\",\n className\n )}\n >\n {options.map((option) => {\n const isActive = selected === option.id;\n const Icon = option.icon;\n\n const pill = (\n <button\n type=\"button\"\n key={option.id}\n onClick={() => handleClick(option.id)}\n disabled={loadingOptionId !== null}\n className={cn(\n \"relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none\",\n sizeClass.button,\n isActive\n ? cn(\n \"bg-background text-foreground shadow-sm ring-1\",\n glassmorphic\n ? \"ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20\"\n : activeRingClass\n )\n : cn(\n \"text-muted-foreground hover:text-foreground\",\n glassmorphic\n ? \"hover:bg-background/50\"\n : \"hover:bg-black/[0.06] dark:hover:bg-white/[0.04]\"\n )\n )}\n >\n {loadingOptionId === option.id && (\n <Spinner\n size={12}\n className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n />\n )}\n <span className={cn(\n \"flex items-center gap-2\",\n loadingOptionId === option.id && \"invisible\"\n )}>\n {Icon && <Icon className={sizeClass.icon} />}\n {showLabels && option.label}\n </span>\n </button>\n );\n\n if (!showLabels) {\n return (\n <Tooltip key={option.id} delayDuration={0}>\n <TooltipTrigger asChild>\n {pill}\n </TooltipTrigger>\n <TooltipPortal>\n <TooltipContent side=\"top\">\n {option.label}\n </TooltipContent>\n </TooltipPortal>\n </Tooltip>\n );\n }\n\n return pill;\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAkCA,MAAM,cAAc,IAAI,IAAqC;CAC3D,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAe,CAAC;CAC9D,CAAC,MAAM;EAAE,QAAQ;EAAqB,MAAM;EAAW,CAAC;CACxD,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAW,CAAC;CAC3D,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAsC;CAChE,CAAC,QAAQ,yCAAyC;CAClD,CAAC,QAAQ,yCAAyC;CAClD,CAAC,UAAU,6CAA6C;CACxD,CAAC,SAAS,+CAA+C;CACzD,CAAC,UAAU,2CAA2C;CACtD,CAAC,WAAW,2CAA2C;CACxD,CAAC;AAEF,SAAS,mBAAiC,KAAwB,KAAW,SAAiB;CAC5F,MAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,WAAW,QAAQ,kBAAkB,OAAO,IAAI,CAAC,GAAG;AAEtE,QAAO;;AAGT,SAAgB,iBAAiB,EAC/B,SACA,UACA,UACA,OAAO,MACP,cAAc,kBACd,WAAW,WACX,aAAa,MACb,aACwB;CACxB,MAAM,qDAAsC,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,aAAa,MAAM,cAAc;CACtE,MAAM,kBAAkB,mBAAmB,iBAAiB,UAAU,kBAAkB;CAExF,MAAM,CAAC,iBAAiB,0CAA8C,KAAK;CAE3E,MAAM,eAAe,aAAqB;EACxC,MAAM,SAAS,SAAS,SAAS;AACjC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,sBAAmB,SAAS;AAC5B,wEACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,mBAAmB,KAAK,CAAC,CAChE;;;AAIL,QACE,2CAAC;EACC,gCACE,iDACA,eACI,0CACA,wCACJ,UACD;YAEA,QAAQ,KAAK,WAAW;GACvB,MAAM,WAAW,aAAa,OAAO;GACrC,MAAM,OAAO,OAAO;GAEpB,MAAM,OACJ,4CAAC;IACC,MAAK;IAEL,eAAe,YAAY,OAAO,GAAG;IACrC,UAAU,oBAAoB;IAC9B,gCACE,6GACA,UAAU,QACV,gCAEI,kDACA,eACI,sHACA,gBACL,wBAEC,+CACA,eACI,2BACA,mDACL,CACJ;eAEA,oBAAoB,OAAO,MAC1B,2CAACA;KACC,MAAM;KACN,WAAU;MACV,EAEJ,4CAAC;KAAK,gCACJ,2BACA,oBAAoB,OAAO,MAAM,YAClC;gBACE,QAAQ,2CAAC,QAAK,WAAW,UAAU,OAAQ,EAC3C,cAAc,OAAO;MACjB;MAjCF,OAAO,GAkCL;AAGX,OAAI,CAAC,WACH,QACE,4CAACC;IAAwB,eAAe;eACtC,2CAACC;KAAe;eACb;MACc,EACjB,2CAACC,mDACC,2CAACC;KAAe,MAAK;eAClB,OAAO;MACO,GACH;MARJ,OAAO,GASX;AAId,UAAO;IACP;GACE"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
|
|
8
8
|
//#region src/components/progress-bar.tsx
|
|
@@ -29,7 +29,7 @@ function DesignProgressBar({ value, max = 100, gradient = "default", label, show
|
|
|
29
29
|
const fillClass = fillClasses.get(gradient) ?? "bg-foreground/60";
|
|
30
30
|
const trackHeight = size === "sm" ? "h-1.5" : size === "lg" ? "h-3" : "h-2";
|
|
31
31
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
32
|
-
className: (0,
|
|
32
|
+
className: (0, _hexclave_ui.cn)("w-full", className),
|
|
33
33
|
children: [(label || showPercentage) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
34
34
|
className: "flex items-center justify-between mb-2",
|
|
35
35
|
children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -40,9 +40,9 @@ function DesignProgressBar({ value, max = 100, gradient = "default", label, show
|
|
|
40
40
|
children: [Math.round(percentage), "%"]
|
|
41
41
|
})]
|
|
42
42
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
43
|
-
className: (0,
|
|
43
|
+
className: (0, _hexclave_ui.cn)("w-full rounded-full bg-black/[0.06] dark:bg-white/[0.06] overflow-hidden", trackHeight),
|
|
44
44
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
45
|
-
className: (0,
|
|
45
|
+
className: (0, _hexclave_ui.cn)("h-full rounded-full transition-all duration-300 ease-out", fillClass),
|
|
46
46
|
style: { width: `${percentage}%` }
|
|
47
47
|
})
|
|
48
48
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-bar.js","names":[],"sources":["../../src/components/progress-bar.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@
|
|
1
|
+
{"version":3,"file":"progress-bar.js","names":[],"sources":["../../src/components/progress-bar.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@hexclave/ui\";\n\ntype DesignProgressBarGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst fillClasses = new Map<DesignProgressBarGradient, string>([\n [\"blue\", \"bg-blue-500 dark:bg-blue-400\"],\n [\"cyan\", \"bg-cyan-500 dark:bg-cyan-400\"],\n [\"purple\", \"bg-purple-500 dark:bg-purple-400\"],\n [\"green\", \"bg-emerald-500 dark:bg-emerald-400\"],\n [\"orange\", \"bg-amber-500 dark:bg-amber-400\"],\n [\"default\", \"bg-foreground/60\"],\n]);\n\nexport type DesignProgressBarProps = {\n value: number,\n max?: number,\n gradient?: DesignProgressBarGradient,\n label?: string,\n showPercentage?: boolean,\n size?: \"sm\" | \"md\" | \"lg\",\n className?: string,\n};\n\n/**\n * Horizontal progress bar for quota / fill-level indicators. Takes a\n * `value` and optional `max` (defaults to 100 — pass raw values, the\n * component computes the percentage). Optional label + percentage display.\n *\n * ```tsx\n * <DesignProgressBar value={usedSeats} max={totalSeats} label=\"Seats used\" showPercentage />\n * <DesignProgressBar value={75} gradient=\"green\" />\n * ```\n */\nexport function DesignProgressBar({\n value,\n max = 100,\n gradient = \"default\",\n label,\n showPercentage = false,\n size = \"md\",\n className,\n}: DesignProgressBarProps) {\n const percentage = max > 0 ? Math.min(Math.max((value / max) * 100, 0), 100) : 0;\n const fillClass = fillClasses.get(gradient) ?? \"bg-foreground/60\";\n\n const trackHeight = size === \"sm\" ? \"h-1.5\" : size === \"lg\" ? \"h-3\" : \"h-2\";\n\n return (\n <div className={cn(\"w-full\", className)}>\n {(label || showPercentage) && (\n <div className=\"flex items-center justify-between mb-2\">\n {label && (\n <span className=\"text-xs font-medium text-muted-foreground\">\n {label}\n </span>\n )}\n {showPercentage && (\n <span className=\"text-xs font-medium tabular-nums text-foreground\">\n {Math.round(percentage)}%\n </span>\n )}\n </div>\n )}\n <div\n className={cn(\n \"w-full rounded-full bg-black/[0.06] dark:bg-white/[0.06] overflow-hidden\",\n trackHeight\n )}\n >\n <div\n className={cn(\n \"h-full rounded-full transition-all duration-300 ease-out\",\n fillClass\n )}\n style={{ width: `${percentage}%` }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAMA,MAAM,cAAc,IAAI,IAAuC;CAC7D,CAAC,QAAQ,+BAA+B;CACxC,CAAC,QAAQ,+BAA+B;CACxC,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,qCAAqC;CAC/C,CAAC,UAAU,iCAAiC;CAC5C,CAAC,WAAW,mBAAmB;CAChC,CAAC;;;;;;;;;;;AAsBF,SAAgB,kBAAkB,EAChC,OACA,MAAM,KACN,WAAW,WACX,OACA,iBAAiB,OACjB,OAAO,MACP,aACyB;CACzB,MAAM,aAAa,MAAM,IAAI,KAAK,IAAI,KAAK,IAAK,QAAQ,MAAO,KAAK,EAAE,EAAE,IAAI,GAAG;CAC/E,MAAM,YAAY,YAAY,IAAI,SAAS,IAAI;CAE/C,MAAM,cAAc,SAAS,OAAO,UAAU,SAAS,OAAO,QAAQ;AAEtE,QACE,4CAAC;EAAI,gCAAc,UAAU,UAAU;cACnC,SAAS,mBACT,4CAAC;GAAI,WAAU;cACZ,SACC,2CAAC;IAAK,WAAU;cACb;KACI,EAER,kBACC,4CAAC;IAAK,WAAU;eACb,KAAK,MAAM,WAAW,EAAC;KACnB;IAEL,EAER,2CAAC;GACC,gCACE,4EACA,YACD;aAED,2CAAC;IACC,gCACE,4DACA,UACD;IACD,OAAO,EAAE,OAAO,GAAG,WAAW,IAAI;KAClC;IACE;GACF"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../chunk-BE-pF4vm.js');
|
|
5
|
-
let
|
|
5
|
+
let _hexclave_ui = require("@hexclave/ui");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
|
|
8
8
|
//#region src/components/separator.tsx
|
|
@@ -19,7 +19,7 @@ function DesignSeparator({ orientation = "horizontal", className, ...props }) {
|
|
|
19
19
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
20
20
|
role: "separator",
|
|
21
21
|
"aria-orientation": orientation,
|
|
22
|
-
className: (0,
|
|
22
|
+
className: (0, _hexclave_ui.cn)(orientation === "horizontal" ? "h-[1px] w-full bg-black/[0.08] dark:bg-white/[0.06]" : "w-[1px] h-full bg-black/[0.08] dark:bg-white/[0.06]", className),
|
|
23
23
|
...props
|
|
24
24
|
});
|
|
25
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"separator.js","names":[],"sources":["../../src/components/separator.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@
|
|
1
|
+
{"version":3,"file":"separator.js","names":[],"sources":["../../src/components/separator.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@hexclave/ui\";\n\nexport type DesignSeparatorProps = {\n orientation?: \"horizontal\" | \"vertical\",\n} & React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Thin divider line. Use `orientation=\"vertical\"` inside a flex row to\n * separate inline groups, or omit for a horizontal rule between sections.\n *\n * ```tsx\n * <DesignSeparator />\n * <DesignSeparator orientation=\"vertical\" className=\"h-6\" />\n * ```\n */\nexport function DesignSeparator({\n orientation = \"horizontal\",\n className,\n ...props\n}: DesignSeparatorProps) {\n return (\n <div\n role=\"separator\"\n aria-orientation={orientation}\n className={cn(\n orientation === \"horizontal\"\n ? \"h-[1px] w-full bg-black/[0.08] dark:bg-white/[0.06]\"\n : \"w-[1px] h-full bg-black/[0.08] dark:bg-white/[0.06]\",\n className\n )}\n {...props}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,EAC9B,cAAc,cACd,WACA,GAAG,SACoB;AACvB,QACE,2CAAC;EACC,MAAK;EACL,oBAAkB;EAClB,gCACE,gBAAgB,eACZ,wDACA,uDACJ,UACD;EACD,GAAI;GACJ"}
|