@humain/ui 2.1.62 → 2.1.65
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/organisms/ai/AIToolCall/AIToolCall.d.ts +9 -3
- package/dist/components/organisms/ai/AIToolRun/index.d.ts +1 -1
- package/dist/components/organisms/ai/AIToolRun/validation.d.ts +24 -3
- package/dist/components/organisms/ai/_shared/format-ai-duration.d.ts +1 -0
- package/dist/components/organisms/ai/_shared/workflow-step-renderer.d.ts +1 -0
- package/dist/index.js +52 -52
- package/dist/index151.js +1 -1
- package/dist/index174.js +10 -333
- package/dist/index174.js.map +1 -1
- package/dist/index175.js +310 -137
- package/dist/index175.js.map +1 -1
- package/dist/index176.js +148 -174
- package/dist/index176.js.map +1 -1
- package/dist/index177.js +186 -78
- package/dist/index177.js.map +1 -1
- package/dist/index178.js +74 -124
- package/dist/index178.js.map +1 -1
- package/dist/index179.js +133 -1
- package/dist/index179.js.map +1 -0
- package/dist/index180.js +2 -201
- package/dist/index181.js +201 -0
- package/dist/{index180.js.map → index181.js.map} +1 -1
- package/dist/index183.js +130 -166
- package/dist/index183.js.map +1 -1
- package/dist/index184.js +195 -983
- package/dist/index184.js.map +1 -1
- package/dist/index185.js +1069 -369
- package/dist/index185.js.map +1 -1
- package/dist/index186.js +395 -197
- package/dist/index186.js.map +1 -1
- package/dist/index187.js +198 -243
- package/dist/index187.js.map +1 -1
- package/dist/index188.js +263 -3
- package/dist/index188.js.map +1 -1
- package/dist/index189.js +3 -209
- package/dist/index189.js.map +1 -1
- package/dist/index190.js +190 -777
- package/dist/index190.js.map +1 -1
- package/dist/index191.js +771 -252
- package/dist/index191.js.map +1 -1
- package/dist/index192.js +250 -65
- package/dist/index192.js.map +1 -1
- package/dist/index193.js +72 -523
- package/dist/index193.js.map +1 -1
- package/dist/index194.js +537 -144
- package/dist/index194.js.map +1 -1
- package/dist/index195.js +139 -720
- package/dist/index195.js.map +1 -1
- package/dist/index196.js +707 -167
- package/dist/index196.js.map +1 -1
- package/dist/index197.js +175 -151
- package/dist/index197.js.map +1 -1
- package/dist/index198.js +152 -487
- package/dist/index198.js.map +1 -1
- package/dist/index199.js +472 -225
- package/dist/index199.js.map +1 -1
- package/dist/index200.js +236 -260
- package/dist/index200.js.map +1 -1
- package/dist/index201.js +265 -215
- package/dist/index201.js.map +1 -1
- package/dist/index202.js +207 -307
- package/dist/index202.js.map +1 -1
- package/dist/index203.js +302 -135
- package/dist/index203.js.map +1 -1
- package/dist/index204.js +140 -271
- package/dist/index204.js.map +1 -1
- package/dist/index205.js +263 -253
- package/dist/index205.js.map +1 -1
- package/dist/index206.js +244 -137
- package/dist/index206.js.map +1 -1
- package/dist/index207.js +100 -238
- package/dist/index207.js.map +1 -1
- package/dist/index208.js +278 -74
- package/dist/index208.js.map +1 -1
- package/dist/index209.js +56 -97
- package/dist/index209.js.map +1 -1
- package/dist/index210.js +142 -47
- package/dist/index210.js.map +1 -1
- package/dist/index211.js +38 -84
- package/dist/index211.js.map +1 -1
- package/dist/index212.js +72 -252
- package/dist/index212.js.map +1 -1
- package/dist/index213.js +274 -26
- package/dist/index213.js.map +1 -1
- package/dist/index214.js +29 -94
- package/dist/index214.js.map +1 -1
- package/dist/index215.js +98 -25
- package/dist/index215.js.map +1 -1
- package/dist/index216.js +20 -565
- package/dist/index216.js.map +1 -1
- package/dist/index217.js +564 -17
- package/dist/index217.js.map +1 -1
- package/dist/index218.js +20 -23
- package/dist/index218.js.map +1 -1
- package/dist/index219.js +20 -95
- package/dist/index219.js.map +1 -1
- package/dist/index220.js +92 -88
- package/dist/index220.js.map +1 -1
- package/dist/index221.js +97 -29
- package/dist/index221.js.map +1 -1
- package/dist/index222.js +24 -470
- package/dist/index222.js.map +1 -1
- package/dist/index223.js +446 -196
- package/dist/index223.js.map +1 -1
- package/dist/index224.js +199 -729
- package/dist/index224.js.map +1 -1
- package/dist/index225.js +750 -61
- package/dist/index225.js.map +1 -1
- package/dist/index226.js +58 -181
- package/dist/index226.js.map +1 -1
- package/dist/index227.js +175 -259
- package/dist/index227.js.map +1 -1
- package/dist/index228.js +246 -172
- package/dist/index228.js.map +1 -1
- package/dist/index229.js +195 -32
- package/dist/index229.js.map +1 -1
- package/dist/index230.js +12 -40
- package/dist/index230.js.map +1 -1
- package/dist/index231.js +23 -26
- package/dist/index231.js.map +1 -1
- package/dist/index232.js +45 -22
- package/dist/index232.js.map +1 -1
- package/dist/index233.js +27 -48
- package/dist/index233.js.map +1 -1
- package/dist/index234.js +52 -26
- package/dist/index234.js.map +1 -1
- package/dist/index235.js +40 -225
- package/dist/index235.js.map +1 -1
- package/dist/index236.js +217 -39
- package/dist/index236.js.map +1 -1
- package/dist/index237.js +50 -0
- package/dist/index237.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/wc/AIToolCall.js +218 -0
- package/dist/wc/AIToolCall.js.map +1 -0
- package/dist/wc/hf-ai-tool-call.js +34 -219
- package/dist/wc/hf-ai-tool-call.js.map +1 -1
- package/dist/wc/hf-ai-tool-run.js +673 -576
- package/dist/wc/hf-ai-tool-run.js.map +1 -1
- package/dist/wc/workflow-step-renderer.js +94 -86
- package/dist/wc/workflow-step-renderer.js.map +1 -1
- package/dist/wc-react/AIToolCall.js +218 -0
- package/dist/wc-react/AIToolCall.js.map +1 -0
- package/dist/wc-react/hf-ai-tool-call.js +32 -217
- package/dist/wc-react/hf-ai-tool-call.js.map +1 -1
- package/dist/wc-react/hf-ai-tool-run.js +698 -601
- package/dist/wc-react/hf-ai-tool-run.js.map +1 -1
- package/dist/wc-react/workflow-step-renderer.js +76 -68
- package/dist/wc-react/workflow-step-renderer.js.map +1 -1
- package/package.json +1 -1
- package/skills/humain-ui/SKILL.md +1 -1
- package/skills/humain-ui-wc/SKILL.md +1 -1
- package/skills/humain-ui-wc.skill +0 -0
- package/skills/humain-ui.skill +0 -0
- package/dist/index182.js +0 -143
- package/dist/index182.js.map +0 -1
- package/dist/wc/wrench.js +0 -10
- package/dist/wc/wrench.js.map +0 -1
- package/dist/wc-react/wrench.js +0 -10
- package/dist/wc-react/wrench.js.map +0 -1
package/dist/index179.js
CHANGED
|
@@ -1,2 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./index2.js";
|
|
3
|
+
import { useAIInteraction } from "./index138.js";
|
|
4
|
+
import { validateTableBlockSchema } from "./index143.js";
|
|
5
|
+
import { Checkbox } from "./index161.js";
|
|
6
|
+
import { Table as TableNamespace, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./index178.js";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/components/organisms/ai/AITable/AITable.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Get the row ID from a data row
|
|
12
|
+
* Uses 'id' field if available, otherwise falls back to first column key
|
|
13
|
+
*/
|
|
14
|
+
function getRowId(row, columns, index) {
|
|
15
|
+
if (row.id !== void 0) {
|
|
16
|
+
const id = String(row.id);
|
|
17
|
+
if (id) return id;
|
|
18
|
+
}
|
|
19
|
+
if (columns.length > 0) {
|
|
20
|
+
const firstKey = columns[0].key;
|
|
21
|
+
const id = String(row[firstKey] ?? "");
|
|
22
|
+
if (id) return id;
|
|
23
|
+
}
|
|
24
|
+
return `row-${index + 1}`;
|
|
25
|
+
}
|
|
26
|
+
function InvalidTableSchema({ className }) {
|
|
27
|
+
return /* @__PURE__ */ jsx("div", {
|
|
28
|
+
"data-slot": "ai-table",
|
|
29
|
+
role: "alert",
|
|
30
|
+
className: cn("rounded-lg border border-destructive bg-destructive/20 p-4 text-sm text-destructive", className),
|
|
31
|
+
children: "Invalid table schema"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* AITable - Renders interactive data tables from JSON schema.
|
|
36
|
+
*
|
|
37
|
+
* Supports row selection with checkboxes and emits interaction events
|
|
38
|
+
* through the AIInteractionContext when selections change.
|
|
39
|
+
*/
|
|
40
|
+
function AITable({ schema, className }) {
|
|
41
|
+
const { onInteraction } = useAIInteraction();
|
|
42
|
+
const tableSchema = React.useMemo(() => validateTableBlockSchema(schema) ? schema : null, [schema]);
|
|
43
|
+
const [selectedRows, setSelectedRows] = React.useState(/* @__PURE__ */ new Set());
|
|
44
|
+
const id = tableSchema?.id ?? "";
|
|
45
|
+
const title = tableSchema?.title;
|
|
46
|
+
const columns = tableSchema?.columns ?? [];
|
|
47
|
+
const data = tableSchema?.data ?? [];
|
|
48
|
+
const selectable = tableSchema?.selectable ?? false;
|
|
49
|
+
const allRowIds = React.useMemo(() => data.map((row, index) => getRowId(row, columns, index)), [data, columns]);
|
|
50
|
+
const emitSelectionChange = React.useCallback((newSelectedRows) => {
|
|
51
|
+
onInteraction?.({
|
|
52
|
+
componentId: id,
|
|
53
|
+
componentType: "table",
|
|
54
|
+
action: "select",
|
|
55
|
+
value: { selectedRows: newSelectedRows },
|
|
56
|
+
timestamp: Date.now()
|
|
57
|
+
});
|
|
58
|
+
}, [id, onInteraction]);
|
|
59
|
+
const handleRowSelect = React.useCallback((rowId, checked) => {
|
|
60
|
+
setSelectedRows((prev) => {
|
|
61
|
+
const next = new Set(prev);
|
|
62
|
+
if (checked) next.add(rowId);
|
|
63
|
+
else next.delete(rowId);
|
|
64
|
+
emitSelectionChange(Array.from(next));
|
|
65
|
+
return next;
|
|
66
|
+
});
|
|
67
|
+
}, [emitSelectionChange]);
|
|
68
|
+
const handleSelectAll = React.useCallback((checked) => {
|
|
69
|
+
if (checked) {
|
|
70
|
+
setSelectedRows(new Set(allRowIds));
|
|
71
|
+
emitSelectionChange(allRowIds);
|
|
72
|
+
} else {
|
|
73
|
+
setSelectedRows(/* @__PURE__ */ new Set());
|
|
74
|
+
emitSelectionChange([]);
|
|
75
|
+
}
|
|
76
|
+
}, [allRowIds, emitSelectionChange]);
|
|
77
|
+
const allSelected = allRowIds.length > 0 && selectedRows.size === allRowIds.length;
|
|
78
|
+
const someSelected = selectedRows.size > 0 && selectedRows.size < allRowIds.length;
|
|
79
|
+
if (!tableSchema) return /* @__PURE__ */ jsx(InvalidTableSchema, { className });
|
|
80
|
+
if (!data || data.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
81
|
+
"data-slot": "ai-table",
|
|
82
|
+
role: "status",
|
|
83
|
+
className: cn("flex items-center justify-center rounded-lg border border-border bg-muted p-8 text-muted-foreground", className),
|
|
84
|
+
children: "No data available"
|
|
85
|
+
});
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
87
|
+
"data-slot": "ai-table",
|
|
88
|
+
className: cn("flex flex-col gap-2", className),
|
|
89
|
+
children: [
|
|
90
|
+
title && /* @__PURE__ */ jsx("h3", {
|
|
91
|
+
className: "text-sm font-medium text-foreground",
|
|
92
|
+
children: title
|
|
93
|
+
}),
|
|
94
|
+
selectable && /* @__PURE__ */ jsx("div", {
|
|
95
|
+
className: "sr-only",
|
|
96
|
+
"aria-live": "polite",
|
|
97
|
+
"aria-atomic": "true",
|
|
98
|
+
children: selectedRows.size > 0 ? `${selectedRows.size} of ${allRowIds.length} rows selected` : "No rows selected"
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ jsxs(TableNamespace, {
|
|
101
|
+
"aria-label": title ?? "Interactive data table",
|
|
102
|
+
children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [selectable && /* @__PURE__ */ jsx(TableHead, {
|
|
103
|
+
className: "w-[40px]",
|
|
104
|
+
children: /* @__PURE__ */ jsx(Checkbox, {
|
|
105
|
+
checked: allSelected,
|
|
106
|
+
indeterminate: someSelected,
|
|
107
|
+
onCheckedChange: handleSelectAll,
|
|
108
|
+
"aria-label": "Select all rows"
|
|
109
|
+
})
|
|
110
|
+
}), columns.map((column) => /* @__PURE__ */ jsx(TableHead, {
|
|
111
|
+
style: { width: typeof column.width === "number" ? Number.isFinite(column.width) ? `${column.width}px` : void 0 : column.width },
|
|
112
|
+
children: column.label
|
|
113
|
+
}, column.key))] }) }), /* @__PURE__ */ jsx(TableBody, { children: data.map((row, index) => {
|
|
114
|
+
const rowId = getRowId(row, columns, index);
|
|
115
|
+
const isSelected = selectedRows.has(rowId);
|
|
116
|
+
return /* @__PURE__ */ jsxs(TableRow, {
|
|
117
|
+
"data-state": isSelected ? "selected" : void 0,
|
|
118
|
+
className: "transition-colors",
|
|
119
|
+
children: [selectable && /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Checkbox, {
|
|
120
|
+
checked: isSelected,
|
|
121
|
+
onCheckedChange: (checked) => handleRowSelect(rowId, checked === true),
|
|
122
|
+
"aria-label": `Select row ${rowId}`
|
|
123
|
+
}) }), columns.map((column) => /* @__PURE__ */ jsx(TableCell, { children: String(row[column.key] ?? "") }, column.key))]
|
|
124
|
+
}, rowId);
|
|
125
|
+
}) })]
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
AITable.displayName = "AITable";
|
|
131
|
+
//#endregion
|
|
2
132
|
export { AITable, AITable as default };
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=index179.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index179.js","names":[],"sources":["../src/components/organisms/ai/AITable/AITable.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useAIInteraction } from '@/components/organisms/ai/_shared/interaction-context';\nimport { validateTableBlockSchema } from '@/components/organisms/ai/_shared/schema-validation';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Schema for a table column\n */\nexport interface TableColumnSchema {\n /** Unique key for the column, maps to data field */\n key: string;\n /** Display label for the column header */\n label: string;\n /** Whether the column is sortable (not yet implemented) */\n sortable?: boolean;\n /** Whether cells in this column are editable (not yet implemented) */\n editable?: boolean;\n /** Column width - can be number (pixels) or string (e.g., '100px', '20%') */\n width?: number | string;\n}\n\n/**\n * Schema for configuring an AITable\n */\nexport interface TableBlockSchema {\n /** Unique identifier for the component instance */\n id: string;\n /** Optional title displayed above the table */\n title?: string;\n /** Column definitions */\n columns: TableColumnSchema[];\n /** Array of row data */\n data: Record<string, unknown>[];\n /** Whether rows can be selected with checkboxes */\n selectable?: boolean;\n /** Pagination configuration (not yet implemented) */\n pagination?: boolean | { pageSize: number };\n}\n\n/**\n * Props for AITable\n */\nexport interface AITableProps {\n /** Schema defining the table configuration */\n schema: TableBlockSchema;\n /** Additional class names */\n className?: string;\n}\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Get the row ID from a data row\n * Uses 'id' field if available, otherwise falls back to first column key\n */\nfunction getRowId(\n row: Record<string, unknown>,\n columns: TableColumnSchema[],\n index: number,\n): string {\n if (row.id !== undefined) {\n const id = String(row.id);\n if (id) {\n return id;\n }\n }\n if (columns.length > 0) {\n const firstKey = columns[0].key;\n const id = String(row[firstKey] ?? '');\n if (id) {\n return id;\n }\n }\n return `row-${index + 1}`;\n}\n\nfunction InvalidTableSchema({\n className,\n}: {\n className?: string;\n}): React.ReactElement {\n return (\n <div\n data-slot=\"ai-table\"\n role=\"alert\"\n className={cn(\n 'rounded-lg border border-destructive bg-destructive/20 p-4 text-sm text-destructive',\n className,\n )}\n >\n Invalid table schema\n </div>\n );\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\n/**\n * AITable - Renders interactive data tables from JSON schema.\n *\n * Supports row selection with checkboxes and emits interaction events\n * through the AIInteractionContext when selections change.\n */\nexport function AITable({\n schema,\n className,\n}: AITableProps): React.ReactElement {\n const { onInteraction } = useAIInteraction();\n const tableSchema = React.useMemo(\n () => (validateTableBlockSchema(schema) ? schema : null),\n [schema],\n );\n const [selectedRows, setSelectedRows] = React.useState<Set<string>>(\n new Set(),\n );\n\n const id = tableSchema?.id ?? '';\n const title = tableSchema?.title;\n const columns = tableSchema?.columns ?? [];\n const data = tableSchema?.data ?? [];\n const selectable = tableSchema?.selectable ?? false;\n\n // Get all row IDs\n const allRowIds = React.useMemo(\n () => data.map((row, index) => getRowId(row, columns, index)),\n [data, columns],\n );\n\n // Emit interaction event when selection changes\n const emitSelectionChange = React.useCallback(\n (newSelectedRows: string[]) => {\n onInteraction?.({\n componentId: id,\n componentType: 'table',\n action: 'select',\n value: { selectedRows: newSelectedRows },\n timestamp: Date.now(),\n });\n },\n [id, onInteraction],\n );\n\n // Handle individual row selection\n const handleRowSelect = React.useCallback(\n (rowId: string, checked: boolean) => {\n setSelectedRows((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(rowId);\n } else {\n next.delete(rowId);\n }\n emitSelectionChange(Array.from(next));\n return next;\n });\n },\n [emitSelectionChange],\n );\n\n // Handle select all\n const handleSelectAll = React.useCallback(\n (checked: boolean) => {\n if (checked) {\n setSelectedRows(new Set(allRowIds));\n emitSelectionChange(allRowIds);\n } else {\n setSelectedRows(new Set());\n emitSelectionChange([]);\n }\n },\n [allRowIds, emitSelectionChange],\n );\n\n // Check if all rows are selected\n const allSelected =\n allRowIds.length > 0 && selectedRows.size === allRowIds.length;\n const someSelected =\n selectedRows.size > 0 && selectedRows.size < allRowIds.length;\n\n if (!tableSchema) {\n return <InvalidTableSchema className={className} />;\n }\n\n // Empty state\n if (!data || data.length === 0) {\n return (\n <div\n data-slot=\"ai-table\"\n role=\"status\"\n className={cn(\n 'flex items-center justify-center rounded-lg border border-border bg-muted p-8 text-muted-foreground',\n className,\n )}\n >\n No data available\n </div>\n );\n }\n\n return (\n <div data-slot=\"ai-table\" className={cn('flex flex-col gap-2', className)}>\n {title && (\n <h3 className=\"text-sm font-medium text-foreground\">{title}</h3>\n )}\n\n {/* Live region for selection count */}\n {selectable && (\n <div className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {selectedRows.size > 0\n ? `${selectedRows.size} of ${allRowIds.length} rows selected`\n : 'No rows selected'}\n </div>\n )}\n\n <Table aria-label={title ?? 'Interactive data table'}>\n <TableHeader>\n <TableRow>\n {selectable && (\n <TableHead className=\"w-[40px]\">\n <Checkbox\n checked={allSelected}\n indeterminate={someSelected}\n onCheckedChange={handleSelectAll}\n aria-label=\"Select all rows\"\n />\n </TableHead>\n )}\n {columns.map((column) => (\n <TableHead\n key={column.key}\n style={{\n width:\n typeof column.width === 'number'\n ? Number.isFinite(column.width)\n ? `${column.width}px`\n : undefined\n : column.width,\n }}\n >\n {column.label}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {data.map((row, index) => {\n const rowId = getRowId(row, columns, index);\n const isSelected = selectedRows.has(rowId);\n\n return (\n <TableRow\n key={rowId}\n data-state={isSelected ? 'selected' : undefined}\n className=\"transition-colors\"\n >\n {selectable && (\n <TableCell>\n <Checkbox\n checked={isSelected}\n onCheckedChange={(checked) =>\n handleRowSelect(rowId, checked === true)\n }\n aria-label={`Select row ${rowId}`}\n />\n </TableCell>\n )}\n {columns.map((column) => (\n <TableCell key={column.key}>\n {String(row[column.key] ?? '')}\n </TableCell>\n ))}\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nAITable.displayName = 'AITable';\n\nexport default AITable;\n"],"mappings":"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"}
|
package/dist/index180.js
CHANGED
|
@@ -1,201 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { motion, useReducedMotion } from "motion/react";
|
|
6
|
-
//#region src/components/organisms/ai/AITextShimmer/AITextShimmer.tsx
|
|
7
|
-
var textShimmerVariants = cva("inline-block", {
|
|
8
|
-
variants: { size: {
|
|
9
|
-
xs: "text-xs",
|
|
10
|
-
sm: "text-sm",
|
|
11
|
-
md: "text-base",
|
|
12
|
-
lg: "text-lg",
|
|
13
|
-
xl: "text-xl"
|
|
14
|
-
} },
|
|
15
|
-
defaultVariants: { size: "md" }
|
|
16
|
-
});
|
|
17
|
-
var shimmerPresets = {
|
|
18
|
-
brand: "color-mix(in srgb, var(--primary) 60%, transparent)",
|
|
19
|
-
silver: "color-mix(in srgb, var(--muted-foreground) 50%, transparent)"
|
|
20
|
-
};
|
|
21
|
-
var AITextShimmer = React.forwardRef(({ children, size, duration = 2, variant = "brand", shimmerColor, baseColor = "var(--text-quaternary)", isActive = true, className }, ref) => {
|
|
22
|
-
const prefersReducedMotion = useReducedMotion();
|
|
23
|
-
const resolvedShimmerColor = shimmerColor ?? shimmerPresets[variant];
|
|
24
|
-
if (!isActive || prefersReducedMotion) return /* @__PURE__ */ jsx("span", {
|
|
25
|
-
ref,
|
|
26
|
-
"data-slot": "ai-text-shimmer",
|
|
27
|
-
className: cn(textShimmerVariants({ size }), className),
|
|
28
|
-
style: { color: baseColor },
|
|
29
|
-
children
|
|
30
|
-
});
|
|
31
|
-
return /* @__PURE__ */ jsx(motion.span, {
|
|
32
|
-
ref,
|
|
33
|
-
"data-slot": "ai-text-shimmer",
|
|
34
|
-
"aria-busy": "true",
|
|
35
|
-
className: cn(textShimmerVariants({ size }), "bg-clip-text text-transparent bg-[length:200%_100%] will-change-[background-position]", className),
|
|
36
|
-
style: { backgroundImage: `linear-gradient(
|
|
37
|
-
90deg,
|
|
38
|
-
${baseColor} 0%,
|
|
39
|
-
${baseColor} 25%,
|
|
40
|
-
${resolvedShimmerColor} 50%,
|
|
41
|
-
${baseColor} 75%,
|
|
42
|
-
${baseColor} 100%
|
|
43
|
-
)` },
|
|
44
|
-
animate: { backgroundPosition: ["200% 0", "-200% 0"] },
|
|
45
|
-
transition: {
|
|
46
|
-
duration,
|
|
47
|
-
repeat: Number.POSITIVE_INFINITY,
|
|
48
|
-
ease: "linear"
|
|
49
|
-
},
|
|
50
|
-
children
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
AITextShimmer.displayName = "AITextShimmer";
|
|
54
|
-
var dotSizes = {
|
|
55
|
-
sm: "size-1",
|
|
56
|
-
md: "size-1.5",
|
|
57
|
-
lg: "size-2"
|
|
58
|
-
};
|
|
59
|
-
var dotGaps = {
|
|
60
|
-
sm: "gap-0.5",
|
|
61
|
-
md: "gap-1",
|
|
62
|
-
lg: "gap-1.5"
|
|
63
|
-
};
|
|
64
|
-
var AILoadingDots = React.forwardRef(({ size = "md", color = "bg-muted", className }, ref) => {
|
|
65
|
-
const prefersReducedMotion = useReducedMotion();
|
|
66
|
-
return /* @__PURE__ */ jsx("span", {
|
|
67
|
-
ref,
|
|
68
|
-
"data-slot": "ai-loading-dots",
|
|
69
|
-
role: "status",
|
|
70
|
-
"aria-label": "Loading",
|
|
71
|
-
className: cn("inline-flex items-center", dotGaps[size], className),
|
|
72
|
-
children: [
|
|
73
|
-
0,
|
|
74
|
-
1,
|
|
75
|
-
2
|
|
76
|
-
].map((i) => /* @__PURE__ */ jsx(motion.span, {
|
|
77
|
-
className: cn("rounded-full will-change-transform", dotSizes[size], color),
|
|
78
|
-
animate: prefersReducedMotion ? {
|
|
79
|
-
y: 0,
|
|
80
|
-
opacity: .75
|
|
81
|
-
} : {
|
|
82
|
-
y: [
|
|
83
|
-
0,
|
|
84
|
-
-2,
|
|
85
|
-
0
|
|
86
|
-
],
|
|
87
|
-
opacity: [
|
|
88
|
-
.4,
|
|
89
|
-
1,
|
|
90
|
-
.4
|
|
91
|
-
]
|
|
92
|
-
},
|
|
93
|
-
transition: prefersReducedMotion ? void 0 : {
|
|
94
|
-
duration: 1,
|
|
95
|
-
repeat: Number.POSITIVE_INFINITY,
|
|
96
|
-
ease: [
|
|
97
|
-
.4,
|
|
98
|
-
0,
|
|
99
|
-
.2,
|
|
100
|
-
1
|
|
101
|
-
],
|
|
102
|
-
delay: i * .15
|
|
103
|
-
},
|
|
104
|
-
"aria-hidden": "true"
|
|
105
|
-
}, i))
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
AILoadingDots.displayName = "AILoadingDots";
|
|
109
|
-
var AITypingText = React.forwardRef(({ texts, typingSpeed = 50, pauseDuration = 1500, className }, ref) => {
|
|
110
|
-
const [currentTextIndex, setCurrentTextIndex] = React.useState(0);
|
|
111
|
-
const [displayedText, setDisplayedText] = React.useState("");
|
|
112
|
-
const [isDeleting, setIsDeleting] = React.useState(false);
|
|
113
|
-
React.useEffect(() => {
|
|
114
|
-
const currentFullText = texts[currentTextIndex] ?? "";
|
|
115
|
-
const isPaused = !isDeleting && displayedText.length >= currentFullText.length;
|
|
116
|
-
const timer = setTimeout(() => {
|
|
117
|
-
if (!isDeleting) if (displayedText.length < currentFullText.length) setDisplayedText(currentFullText.slice(0, displayedText.length + 1));
|
|
118
|
-
else setIsDeleting(true);
|
|
119
|
-
else if (displayedText.length > 0) setDisplayedText(currentFullText.slice(0, displayedText.length - 1));
|
|
120
|
-
else {
|
|
121
|
-
setIsDeleting(false);
|
|
122
|
-
setCurrentTextIndex((prev) => (prev + 1) % texts.length);
|
|
123
|
-
}
|
|
124
|
-
}, isPaused ? pauseDuration : isDeleting ? typingSpeed / 2 : typingSpeed);
|
|
125
|
-
return () => {
|
|
126
|
-
clearTimeout(timer);
|
|
127
|
-
};
|
|
128
|
-
}, [
|
|
129
|
-
displayedText,
|
|
130
|
-
isDeleting,
|
|
131
|
-
currentTextIndex,
|
|
132
|
-
texts,
|
|
133
|
-
typingSpeed,
|
|
134
|
-
pauseDuration
|
|
135
|
-
]);
|
|
136
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
137
|
-
ref,
|
|
138
|
-
"data-slot": "ai-typing-text",
|
|
139
|
-
role: "status",
|
|
140
|
-
"aria-label": texts[currentTextIndex],
|
|
141
|
-
className: cn("inline-flex items-center", className),
|
|
142
|
-
children: [displayedText, /* @__PURE__ */ jsx(motion.span, {
|
|
143
|
-
className: "inline-block w-0.5 h-[1em] bg-muted-foreground ms-0.5 motion-reduce:animate-none motion-reduce:opacity-100",
|
|
144
|
-
animate: { opacity: [
|
|
145
|
-
1,
|
|
146
|
-
.15,
|
|
147
|
-
1
|
|
148
|
-
] },
|
|
149
|
-
transition: {
|
|
150
|
-
duration: 1,
|
|
151
|
-
repeat: Number.POSITIVE_INFINITY,
|
|
152
|
-
ease: "easeInOut"
|
|
153
|
-
},
|
|
154
|
-
"aria-hidden": "true"
|
|
155
|
-
})]
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
AITypingText.displayName = "AITypingText";
|
|
159
|
-
var AIPulseText = React.forwardRef(({ children, isActive = true, className }, ref) => {
|
|
160
|
-
const prefersReducedMotion = useReducedMotion();
|
|
161
|
-
if (!isActive || prefersReducedMotion) return /* @__PURE__ */ jsx("span", {
|
|
162
|
-
ref,
|
|
163
|
-
"data-slot": "ai-pulse-text",
|
|
164
|
-
role: "status",
|
|
165
|
-
"aria-label": children,
|
|
166
|
-
className,
|
|
167
|
-
children
|
|
168
|
-
});
|
|
169
|
-
return /* @__PURE__ */ jsx(motion.span, {
|
|
170
|
-
ref,
|
|
171
|
-
"data-slot": "ai-pulse-text",
|
|
172
|
-
role: "status",
|
|
173
|
-
"aria-label": children,
|
|
174
|
-
className,
|
|
175
|
-
animate: { opacity: [
|
|
176
|
-
.4,
|
|
177
|
-
1,
|
|
178
|
-
.7,
|
|
179
|
-
1,
|
|
180
|
-
.4
|
|
181
|
-
] },
|
|
182
|
-
transition: {
|
|
183
|
-
duration: 2.5,
|
|
184
|
-
repeat: Number.POSITIVE_INFINITY,
|
|
185
|
-
times: [
|
|
186
|
-
0,
|
|
187
|
-
.3,
|
|
188
|
-
.5,
|
|
189
|
-
.7,
|
|
190
|
-
1
|
|
191
|
-
],
|
|
192
|
-
ease: "easeInOut"
|
|
193
|
-
},
|
|
194
|
-
children
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
AIPulseText.displayName = "AIPulseText";
|
|
198
|
-
//#endregion
|
|
199
|
-
export { AILoadingDots, AIPulseText, AITextShimmer, AITypingText, shimmerPresets, textShimmerVariants };
|
|
200
|
-
|
|
201
|
-
//# sourceMappingURL=index180.js.map
|
|
1
|
+
import { AITable } from "./index179.js";
|
|
2
|
+
export { AITable, AITable as default };
|
package/dist/index181.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { cn } from "./index2.js";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
6
|
+
//#region src/components/organisms/ai/AITextShimmer/AITextShimmer.tsx
|
|
7
|
+
var textShimmerVariants = cva("inline-block", {
|
|
8
|
+
variants: { size: {
|
|
9
|
+
xs: "text-xs",
|
|
10
|
+
sm: "text-sm",
|
|
11
|
+
md: "text-base",
|
|
12
|
+
lg: "text-lg",
|
|
13
|
+
xl: "text-xl"
|
|
14
|
+
} },
|
|
15
|
+
defaultVariants: { size: "md" }
|
|
16
|
+
});
|
|
17
|
+
var shimmerPresets = {
|
|
18
|
+
brand: "color-mix(in srgb, var(--primary) 60%, transparent)",
|
|
19
|
+
silver: "color-mix(in srgb, var(--muted-foreground) 50%, transparent)"
|
|
20
|
+
};
|
|
21
|
+
var AITextShimmer = React.forwardRef(({ children, size, duration = 2, variant = "brand", shimmerColor, baseColor = "var(--text-quaternary)", isActive = true, className }, ref) => {
|
|
22
|
+
const prefersReducedMotion = useReducedMotion();
|
|
23
|
+
const resolvedShimmerColor = shimmerColor ?? shimmerPresets[variant];
|
|
24
|
+
if (!isActive || prefersReducedMotion) return /* @__PURE__ */ jsx("span", {
|
|
25
|
+
ref,
|
|
26
|
+
"data-slot": "ai-text-shimmer",
|
|
27
|
+
className: cn(textShimmerVariants({ size }), className),
|
|
28
|
+
style: { color: baseColor },
|
|
29
|
+
children
|
|
30
|
+
});
|
|
31
|
+
return /* @__PURE__ */ jsx(motion.span, {
|
|
32
|
+
ref,
|
|
33
|
+
"data-slot": "ai-text-shimmer",
|
|
34
|
+
"aria-busy": "true",
|
|
35
|
+
className: cn(textShimmerVariants({ size }), "bg-clip-text text-transparent bg-[length:200%_100%] will-change-[background-position]", className),
|
|
36
|
+
style: { backgroundImage: `linear-gradient(
|
|
37
|
+
90deg,
|
|
38
|
+
${baseColor} 0%,
|
|
39
|
+
${baseColor} 25%,
|
|
40
|
+
${resolvedShimmerColor} 50%,
|
|
41
|
+
${baseColor} 75%,
|
|
42
|
+
${baseColor} 100%
|
|
43
|
+
)` },
|
|
44
|
+
animate: { backgroundPosition: ["200% 0", "-200% 0"] },
|
|
45
|
+
transition: {
|
|
46
|
+
duration,
|
|
47
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
48
|
+
ease: "linear"
|
|
49
|
+
},
|
|
50
|
+
children
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
AITextShimmer.displayName = "AITextShimmer";
|
|
54
|
+
var dotSizes = {
|
|
55
|
+
sm: "size-1",
|
|
56
|
+
md: "size-1.5",
|
|
57
|
+
lg: "size-2"
|
|
58
|
+
};
|
|
59
|
+
var dotGaps = {
|
|
60
|
+
sm: "gap-0.5",
|
|
61
|
+
md: "gap-1",
|
|
62
|
+
lg: "gap-1.5"
|
|
63
|
+
};
|
|
64
|
+
var AILoadingDots = React.forwardRef(({ size = "md", color = "bg-muted", className }, ref) => {
|
|
65
|
+
const prefersReducedMotion = useReducedMotion();
|
|
66
|
+
return /* @__PURE__ */ jsx("span", {
|
|
67
|
+
ref,
|
|
68
|
+
"data-slot": "ai-loading-dots",
|
|
69
|
+
role: "status",
|
|
70
|
+
"aria-label": "Loading",
|
|
71
|
+
className: cn("inline-flex items-center", dotGaps[size], className),
|
|
72
|
+
children: [
|
|
73
|
+
0,
|
|
74
|
+
1,
|
|
75
|
+
2
|
|
76
|
+
].map((i) => /* @__PURE__ */ jsx(motion.span, {
|
|
77
|
+
className: cn("rounded-full will-change-transform", dotSizes[size], color),
|
|
78
|
+
animate: prefersReducedMotion ? {
|
|
79
|
+
y: 0,
|
|
80
|
+
opacity: .75
|
|
81
|
+
} : {
|
|
82
|
+
y: [
|
|
83
|
+
0,
|
|
84
|
+
-2,
|
|
85
|
+
0
|
|
86
|
+
],
|
|
87
|
+
opacity: [
|
|
88
|
+
.4,
|
|
89
|
+
1,
|
|
90
|
+
.4
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
transition: prefersReducedMotion ? void 0 : {
|
|
94
|
+
duration: 1,
|
|
95
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
96
|
+
ease: [
|
|
97
|
+
.4,
|
|
98
|
+
0,
|
|
99
|
+
.2,
|
|
100
|
+
1
|
|
101
|
+
],
|
|
102
|
+
delay: i * .15
|
|
103
|
+
},
|
|
104
|
+
"aria-hidden": "true"
|
|
105
|
+
}, i))
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
AILoadingDots.displayName = "AILoadingDots";
|
|
109
|
+
var AITypingText = React.forwardRef(({ texts, typingSpeed = 50, pauseDuration = 1500, className }, ref) => {
|
|
110
|
+
const [currentTextIndex, setCurrentTextIndex] = React.useState(0);
|
|
111
|
+
const [displayedText, setDisplayedText] = React.useState("");
|
|
112
|
+
const [isDeleting, setIsDeleting] = React.useState(false);
|
|
113
|
+
React.useEffect(() => {
|
|
114
|
+
const currentFullText = texts[currentTextIndex] ?? "";
|
|
115
|
+
const isPaused = !isDeleting && displayedText.length >= currentFullText.length;
|
|
116
|
+
const timer = setTimeout(() => {
|
|
117
|
+
if (!isDeleting) if (displayedText.length < currentFullText.length) setDisplayedText(currentFullText.slice(0, displayedText.length + 1));
|
|
118
|
+
else setIsDeleting(true);
|
|
119
|
+
else if (displayedText.length > 0) setDisplayedText(currentFullText.slice(0, displayedText.length - 1));
|
|
120
|
+
else {
|
|
121
|
+
setIsDeleting(false);
|
|
122
|
+
setCurrentTextIndex((prev) => (prev + 1) % texts.length);
|
|
123
|
+
}
|
|
124
|
+
}, isPaused ? pauseDuration : isDeleting ? typingSpeed / 2 : typingSpeed);
|
|
125
|
+
return () => {
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
};
|
|
128
|
+
}, [
|
|
129
|
+
displayedText,
|
|
130
|
+
isDeleting,
|
|
131
|
+
currentTextIndex,
|
|
132
|
+
texts,
|
|
133
|
+
typingSpeed,
|
|
134
|
+
pauseDuration
|
|
135
|
+
]);
|
|
136
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
137
|
+
ref,
|
|
138
|
+
"data-slot": "ai-typing-text",
|
|
139
|
+
role: "status",
|
|
140
|
+
"aria-label": texts[currentTextIndex],
|
|
141
|
+
className: cn("inline-flex items-center", className),
|
|
142
|
+
children: [displayedText, /* @__PURE__ */ jsx(motion.span, {
|
|
143
|
+
className: "inline-block w-0.5 h-[1em] bg-muted-foreground ms-0.5 motion-reduce:animate-none motion-reduce:opacity-100",
|
|
144
|
+
animate: { opacity: [
|
|
145
|
+
1,
|
|
146
|
+
.15,
|
|
147
|
+
1
|
|
148
|
+
] },
|
|
149
|
+
transition: {
|
|
150
|
+
duration: 1,
|
|
151
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
152
|
+
ease: "easeInOut"
|
|
153
|
+
},
|
|
154
|
+
"aria-hidden": "true"
|
|
155
|
+
})]
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
AITypingText.displayName = "AITypingText";
|
|
159
|
+
var AIPulseText = React.forwardRef(({ children, isActive = true, className }, ref) => {
|
|
160
|
+
const prefersReducedMotion = useReducedMotion();
|
|
161
|
+
if (!isActive || prefersReducedMotion) return /* @__PURE__ */ jsx("span", {
|
|
162
|
+
ref,
|
|
163
|
+
"data-slot": "ai-pulse-text",
|
|
164
|
+
role: "status",
|
|
165
|
+
"aria-label": children,
|
|
166
|
+
className,
|
|
167
|
+
children
|
|
168
|
+
});
|
|
169
|
+
return /* @__PURE__ */ jsx(motion.span, {
|
|
170
|
+
ref,
|
|
171
|
+
"data-slot": "ai-pulse-text",
|
|
172
|
+
role: "status",
|
|
173
|
+
"aria-label": children,
|
|
174
|
+
className,
|
|
175
|
+
animate: { opacity: [
|
|
176
|
+
.4,
|
|
177
|
+
1,
|
|
178
|
+
.7,
|
|
179
|
+
1,
|
|
180
|
+
.4
|
|
181
|
+
] },
|
|
182
|
+
transition: {
|
|
183
|
+
duration: 2.5,
|
|
184
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
185
|
+
times: [
|
|
186
|
+
0,
|
|
187
|
+
.3,
|
|
188
|
+
.5,
|
|
189
|
+
.7,
|
|
190
|
+
1
|
|
191
|
+
],
|
|
192
|
+
ease: "easeInOut"
|
|
193
|
+
},
|
|
194
|
+
children
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
AIPulseText.displayName = "AIPulseText";
|
|
198
|
+
//#endregion
|
|
199
|
+
export { AILoadingDots, AIPulseText, AITextShimmer, AITypingText, shimmerPresets, textShimmerVariants };
|
|
200
|
+
|
|
201
|
+
//# sourceMappingURL=index181.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index180.js","names":[],"sources":["../src/components/organisms/ai/AITextShimmer/AITextShimmer.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { motion, useReducedMotion } from 'motion/react';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst textShimmerVariants = cva('inline-block', {\n variants: {\n size: {\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// =============================================================================\n// Shimmer color presets\n// =============================================================================\n\nconst shimmerPresets = {\n brand: 'color-mix(in srgb, var(--primary) 60%, transparent)',\n silver: 'color-mix(in srgb, var(--muted-foreground) 50%, transparent)',\n} as const;\n\n// =============================================================================\n// Main AITextShimmer Component\n// =============================================================================\n\nexport interface AITextShimmerProps\n extends VariantProps<typeof textShimmerVariants> {\n /** Text content to display with shimmer effect */\n children: string;\n /** Animation duration in seconds */\n duration?: number;\n /** Shimmer color preset */\n variant?: keyof typeof shimmerPresets;\n /** Custom shimmer color — overrides variant when provided */\n shimmerColor?: string;\n /** Base text color */\n baseColor?: string;\n /** Whether the shimmer is active */\n isActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AITextShimmer = React.forwardRef<HTMLSpanElement, AITextShimmerProps>(\n (\n {\n children,\n size,\n duration = 2,\n variant = 'brand',\n shimmerColor,\n baseColor = 'var(--text-quaternary)',\n isActive = true,\n className,\n },\n ref,\n ) => {\n const prefersReducedMotion = useReducedMotion();\n const resolvedShimmerColor = shimmerColor ?? shimmerPresets[variant];\n\n if (!isActive || prefersReducedMotion) {\n return (\n <span\n ref={ref}\n data-slot=\"ai-text-shimmer\"\n className={cn(textShimmerVariants({ size }), className)}\n style={{ color: baseColor }}\n >\n {children}\n </span>\n );\n }\n\n return (\n <motion.span\n ref={ref}\n data-slot=\"ai-text-shimmer\"\n aria-busy=\"true\"\n className={cn(\n textShimmerVariants({ size }),\n 'bg-clip-text text-transparent bg-[length:200%_100%] will-change-[background-position]',\n className,\n )}\n style={{\n backgroundImage: `linear-gradient(\n 90deg,\n ${baseColor} 0%,\n ${baseColor} 25%,\n ${resolvedShimmerColor} 50%,\n ${baseColor} 75%,\n ${baseColor} 100%\n )`,\n }}\n animate={{\n backgroundPosition: ['200% 0', '-200% 0'],\n }}\n transition={{\n duration,\n repeat: Number.POSITIVE_INFINITY,\n ease: 'linear',\n }}\n >\n {children}\n </motion.span>\n );\n },\n);\n\nAITextShimmer.displayName = 'AITextShimmer';\n\n// =============================================================================\n// Loading Dots Component\n// =============================================================================\n\nconst dotSizes = {\n sm: 'size-1',\n md: 'size-1.5',\n lg: 'size-2',\n} as const;\n\nconst dotGaps = {\n sm: 'gap-0.5',\n md: 'gap-1',\n lg: 'gap-1.5',\n} as const;\n\nexport interface AILoadingDotsProps {\n /** Dot size */\n size?: 'sm' | 'md' | 'lg';\n /** Dot color */\n color?: string;\n /** Additional class name */\n className?: string;\n}\n\nconst AILoadingDots = React.forwardRef<HTMLSpanElement, AILoadingDotsProps>(\n ({ size = 'md', color = 'bg-muted', className }, ref) => {\n const prefersReducedMotion = useReducedMotion();\n\n return (\n <span\n ref={ref}\n data-slot=\"ai-loading-dots\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn('inline-flex items-center', dotGaps[size], className)}\n >\n {[0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className={cn(\n 'rounded-full will-change-transform',\n dotSizes[size],\n color,\n )}\n animate={\n prefersReducedMotion\n ? { y: 0, opacity: 0.75 }\n : {\n y: [0, -2, 0],\n opacity: [0.4, 1, 0.4],\n }\n }\n transition={\n prefersReducedMotion\n ? undefined\n : {\n duration: 1,\n repeat: Number.POSITIVE_INFINITY,\n ease: [0.4, 0, 0.2, 1],\n delay: i * 0.15,\n }\n }\n aria-hidden=\"true\"\n />\n ))}\n </span>\n );\n },\n);\n\nAILoadingDots.displayName = 'AILoadingDots';\n\n// =============================================================================\n// Typing Text Component\n// =============================================================================\n\nexport interface AITypingTextProps {\n /** Text options to cycle through */\n texts: string[];\n /** Typing speed in ms per character */\n typingSpeed?: number;\n /** Pause duration between texts in ms */\n pauseDuration?: number;\n /** Additional class name */\n className?: string;\n}\n\nconst AITypingText = React.forwardRef<HTMLSpanElement, AITypingTextProps>(\n ({ texts, typingSpeed = 50, pauseDuration = 1500, className }, ref) => {\n const [currentTextIndex, setCurrentTextIndex] = React.useState(0);\n const [displayedText, setDisplayedText] = React.useState('');\n const [isDeleting, setIsDeleting] = React.useState(false);\n\n React.useEffect(() => {\n const currentFullText = texts[currentTextIndex] ?? '';\n const isPaused =\n !isDeleting && displayedText.length >= currentFullText.length;\n\n const timer = setTimeout(\n () => {\n if (!isDeleting) {\n if (displayedText.length < currentFullText.length) {\n setDisplayedText(\n currentFullText.slice(0, displayedText.length + 1),\n );\n } else {\n setIsDeleting(true);\n }\n } else {\n if (displayedText.length > 0) {\n setDisplayedText(\n currentFullText.slice(0, displayedText.length - 1),\n );\n } else {\n setIsDeleting(false);\n setCurrentTextIndex((prev) => (prev + 1) % texts.length);\n }\n }\n },\n isPaused ? pauseDuration : isDeleting ? typingSpeed / 2 : typingSpeed,\n );\n\n return () => {\n clearTimeout(timer);\n };\n }, [\n displayedText,\n isDeleting,\n currentTextIndex,\n texts,\n typingSpeed,\n pauseDuration,\n ]);\n\n return (\n <span\n ref={ref}\n data-slot=\"ai-typing-text\"\n role=\"status\"\n aria-label={texts[currentTextIndex]}\n className={cn('inline-flex items-center', className)}\n >\n {displayedText}\n <motion.span\n className=\"inline-block w-0.5 h-[1em] bg-muted-foreground ms-0.5 motion-reduce:animate-none motion-reduce:opacity-100\"\n animate={{ opacity: [1, 0.15, 1] }}\n transition={{\n duration: 1,\n repeat: Number.POSITIVE_INFINITY,\n ease: 'easeInOut',\n }}\n aria-hidden=\"true\"\n />\n </span>\n );\n },\n);\n\nAITypingText.displayName = 'AITypingText';\n\n// =============================================================================\n// Pulse Text Component\n// =============================================================================\n\nexport interface AIPulseTextProps {\n /** Text content */\n children: string;\n /** Whether the pulse is active */\n isActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AIPulseText = React.forwardRef<HTMLSpanElement, AIPulseTextProps>(\n ({ children, isActive = true, className }, ref) => {\n const prefersReducedMotion = useReducedMotion();\n\n if (!isActive || prefersReducedMotion) {\n return (\n <span\n ref={ref}\n data-slot=\"ai-pulse-text\"\n role=\"status\"\n aria-label={children}\n className={className}\n >\n {children}\n </span>\n );\n }\n\n return (\n <motion.span\n ref={ref}\n data-slot=\"ai-pulse-text\"\n role=\"status\"\n aria-label={children}\n className={className}\n animate={{\n opacity: [0.4, 1, 0.7, 1, 0.4],\n }}\n transition={{\n duration: 2.5,\n repeat: Number.POSITIVE_INFINITY,\n times: [0, 0.3, 0.5, 0.7, 1],\n ease: 'easeInOut',\n }}\n >\n {children}\n </motion.span>\n );\n },\n);\n\nAIPulseText.displayName = 'AIPulseText';\n\nexport {\n AILoadingDots,\n AIPulseText,\n AITextShimmer,\n AITypingText,\n shimmerPresets,\n textShimmerVariants,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index181.js","names":[],"sources":["../src/components/organisms/ai/AITextShimmer/AITextShimmer.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport { motion, useReducedMotion } from 'motion/react';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst textShimmerVariants = cva('inline-block', {\n variants: {\n size: {\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-base',\n lg: 'text-lg',\n xl: 'text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// =============================================================================\n// Shimmer color presets\n// =============================================================================\n\nconst shimmerPresets = {\n brand: 'color-mix(in srgb, var(--primary) 60%, transparent)',\n silver: 'color-mix(in srgb, var(--muted-foreground) 50%, transparent)',\n} as const;\n\n// =============================================================================\n// Main AITextShimmer Component\n// =============================================================================\n\nexport interface AITextShimmerProps\n extends VariantProps<typeof textShimmerVariants> {\n /** Text content to display with shimmer effect */\n children: string;\n /** Animation duration in seconds */\n duration?: number;\n /** Shimmer color preset */\n variant?: keyof typeof shimmerPresets;\n /** Custom shimmer color — overrides variant when provided */\n shimmerColor?: string;\n /** Base text color */\n baseColor?: string;\n /** Whether the shimmer is active */\n isActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AITextShimmer = React.forwardRef<HTMLSpanElement, AITextShimmerProps>(\n (\n {\n children,\n size,\n duration = 2,\n variant = 'brand',\n shimmerColor,\n baseColor = 'var(--text-quaternary)',\n isActive = true,\n className,\n },\n ref,\n ) => {\n const prefersReducedMotion = useReducedMotion();\n const resolvedShimmerColor = shimmerColor ?? shimmerPresets[variant];\n\n if (!isActive || prefersReducedMotion) {\n return (\n <span\n ref={ref}\n data-slot=\"ai-text-shimmer\"\n className={cn(textShimmerVariants({ size }), className)}\n style={{ color: baseColor }}\n >\n {children}\n </span>\n );\n }\n\n return (\n <motion.span\n ref={ref}\n data-slot=\"ai-text-shimmer\"\n aria-busy=\"true\"\n className={cn(\n textShimmerVariants({ size }),\n 'bg-clip-text text-transparent bg-[length:200%_100%] will-change-[background-position]',\n className,\n )}\n style={{\n backgroundImage: `linear-gradient(\n 90deg,\n ${baseColor} 0%,\n ${baseColor} 25%,\n ${resolvedShimmerColor} 50%,\n ${baseColor} 75%,\n ${baseColor} 100%\n )`,\n }}\n animate={{\n backgroundPosition: ['200% 0', '-200% 0'],\n }}\n transition={{\n duration,\n repeat: Number.POSITIVE_INFINITY,\n ease: 'linear',\n }}\n >\n {children}\n </motion.span>\n );\n },\n);\n\nAITextShimmer.displayName = 'AITextShimmer';\n\n// =============================================================================\n// Loading Dots Component\n// =============================================================================\n\nconst dotSizes = {\n sm: 'size-1',\n md: 'size-1.5',\n lg: 'size-2',\n} as const;\n\nconst dotGaps = {\n sm: 'gap-0.5',\n md: 'gap-1',\n lg: 'gap-1.5',\n} as const;\n\nexport interface AILoadingDotsProps {\n /** Dot size */\n size?: 'sm' | 'md' | 'lg';\n /** Dot color */\n color?: string;\n /** Additional class name */\n className?: string;\n}\n\nconst AILoadingDots = React.forwardRef<HTMLSpanElement, AILoadingDotsProps>(\n ({ size = 'md', color = 'bg-muted', className }, ref) => {\n const prefersReducedMotion = useReducedMotion();\n\n return (\n <span\n ref={ref}\n data-slot=\"ai-loading-dots\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn('inline-flex items-center', dotGaps[size], className)}\n >\n {[0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className={cn(\n 'rounded-full will-change-transform',\n dotSizes[size],\n color,\n )}\n animate={\n prefersReducedMotion\n ? { y: 0, opacity: 0.75 }\n : {\n y: [0, -2, 0],\n opacity: [0.4, 1, 0.4],\n }\n }\n transition={\n prefersReducedMotion\n ? undefined\n : {\n duration: 1,\n repeat: Number.POSITIVE_INFINITY,\n ease: [0.4, 0, 0.2, 1],\n delay: i * 0.15,\n }\n }\n aria-hidden=\"true\"\n />\n ))}\n </span>\n );\n },\n);\n\nAILoadingDots.displayName = 'AILoadingDots';\n\n// =============================================================================\n// Typing Text Component\n// =============================================================================\n\nexport interface AITypingTextProps {\n /** Text options to cycle through */\n texts: string[];\n /** Typing speed in ms per character */\n typingSpeed?: number;\n /** Pause duration between texts in ms */\n pauseDuration?: number;\n /** Additional class name */\n className?: string;\n}\n\nconst AITypingText = React.forwardRef<HTMLSpanElement, AITypingTextProps>(\n ({ texts, typingSpeed = 50, pauseDuration = 1500, className }, ref) => {\n const [currentTextIndex, setCurrentTextIndex] = React.useState(0);\n const [displayedText, setDisplayedText] = React.useState('');\n const [isDeleting, setIsDeleting] = React.useState(false);\n\n React.useEffect(() => {\n const currentFullText = texts[currentTextIndex] ?? '';\n const isPaused =\n !isDeleting && displayedText.length >= currentFullText.length;\n\n const timer = setTimeout(\n () => {\n if (!isDeleting) {\n if (displayedText.length < currentFullText.length) {\n setDisplayedText(\n currentFullText.slice(0, displayedText.length + 1),\n );\n } else {\n setIsDeleting(true);\n }\n } else {\n if (displayedText.length > 0) {\n setDisplayedText(\n currentFullText.slice(0, displayedText.length - 1),\n );\n } else {\n setIsDeleting(false);\n setCurrentTextIndex((prev) => (prev + 1) % texts.length);\n }\n }\n },\n isPaused ? pauseDuration : isDeleting ? typingSpeed / 2 : typingSpeed,\n );\n\n return () => {\n clearTimeout(timer);\n };\n }, [\n displayedText,\n isDeleting,\n currentTextIndex,\n texts,\n typingSpeed,\n pauseDuration,\n ]);\n\n return (\n <span\n ref={ref}\n data-slot=\"ai-typing-text\"\n role=\"status\"\n aria-label={texts[currentTextIndex]}\n className={cn('inline-flex items-center', className)}\n >\n {displayedText}\n <motion.span\n className=\"inline-block w-0.5 h-[1em] bg-muted-foreground ms-0.5 motion-reduce:animate-none motion-reduce:opacity-100\"\n animate={{ opacity: [1, 0.15, 1] }}\n transition={{\n duration: 1,\n repeat: Number.POSITIVE_INFINITY,\n ease: 'easeInOut',\n }}\n aria-hidden=\"true\"\n />\n </span>\n );\n },\n);\n\nAITypingText.displayName = 'AITypingText';\n\n// =============================================================================\n// Pulse Text Component\n// =============================================================================\n\nexport interface AIPulseTextProps {\n /** Text content */\n children: string;\n /** Whether the pulse is active */\n isActive?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nconst AIPulseText = React.forwardRef<HTMLSpanElement, AIPulseTextProps>(\n ({ children, isActive = true, className }, ref) => {\n const prefersReducedMotion = useReducedMotion();\n\n if (!isActive || prefersReducedMotion) {\n return (\n <span\n ref={ref}\n data-slot=\"ai-pulse-text\"\n role=\"status\"\n aria-label={children}\n className={className}\n >\n {children}\n </span>\n );\n }\n\n return (\n <motion.span\n ref={ref}\n data-slot=\"ai-pulse-text\"\n role=\"status\"\n aria-label={children}\n className={className}\n animate={{\n opacity: [0.4, 1, 0.7, 1, 0.4],\n }}\n transition={{\n duration: 2.5,\n repeat: Number.POSITIVE_INFINITY,\n times: [0, 0.3, 0.5, 0.7, 1],\n ease: 'easeInOut',\n }}\n >\n {children}\n </motion.span>\n );\n },\n);\n\nAIPulseText.displayName = 'AIPulseText';\n\nexport {\n AILoadingDots,\n AIPulseText,\n AITextShimmer,\n AITypingText,\n shimmerPresets,\n textShimmerVariants,\n};\n"],"mappings":"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"}
|