@humain/ui 2.1.63 → 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.
Files changed (160) hide show
  1. package/dist/components/organisms/ai/AIToolCall/AIToolCall.d.ts +9 -3
  2. package/dist/components/organisms/ai/AIToolRun/index.d.ts +1 -1
  3. package/dist/components/organisms/ai/AIToolRun/validation.d.ts +24 -3
  4. package/dist/components/organisms/ai/_shared/format-ai-duration.d.ts +1 -0
  5. package/dist/components/organisms/ai/_shared/workflow-step-renderer.d.ts +1 -0
  6. package/dist/index.js +52 -52
  7. package/dist/index151.js +1 -1
  8. package/dist/index174.js +7 -339
  9. package/dist/index174.js.map +1 -1
  10. package/dist/index175.js +310 -137
  11. package/dist/index175.js.map +1 -1
  12. package/dist/index176.js +148 -174
  13. package/dist/index176.js.map +1 -1
  14. package/dist/index177.js +186 -78
  15. package/dist/index177.js.map +1 -1
  16. package/dist/index178.js +74 -124
  17. package/dist/index178.js.map +1 -1
  18. package/dist/index179.js +133 -1
  19. package/dist/index179.js.map +1 -0
  20. package/dist/index180.js +2 -201
  21. package/dist/index181.js +201 -0
  22. package/dist/{index180.js.map → index181.js.map} +1 -1
  23. package/dist/index183.js +130 -166
  24. package/dist/index183.js.map +1 -1
  25. package/dist/index184.js +195 -983
  26. package/dist/index184.js.map +1 -1
  27. package/dist/index185.js +1069 -369
  28. package/dist/index185.js.map +1 -1
  29. package/dist/index186.js +395 -197
  30. package/dist/index186.js.map +1 -1
  31. package/dist/index187.js +198 -243
  32. package/dist/index187.js.map +1 -1
  33. package/dist/index188.js +263 -3
  34. package/dist/index188.js.map +1 -1
  35. package/dist/index189.js +3 -209
  36. package/dist/index189.js.map +1 -1
  37. package/dist/index190.js +190 -777
  38. package/dist/index190.js.map +1 -1
  39. package/dist/index191.js +771 -252
  40. package/dist/index191.js.map +1 -1
  41. package/dist/index192.js +250 -65
  42. package/dist/index192.js.map +1 -1
  43. package/dist/index193.js +72 -523
  44. package/dist/index193.js.map +1 -1
  45. package/dist/index194.js +537 -144
  46. package/dist/index194.js.map +1 -1
  47. package/dist/index195.js +139 -720
  48. package/dist/index195.js.map +1 -1
  49. package/dist/index196.js +707 -167
  50. package/dist/index196.js.map +1 -1
  51. package/dist/index197.js +175 -151
  52. package/dist/index197.js.map +1 -1
  53. package/dist/index198.js +152 -487
  54. package/dist/index198.js.map +1 -1
  55. package/dist/index199.js +472 -225
  56. package/dist/index199.js.map +1 -1
  57. package/dist/index200.js +236 -260
  58. package/dist/index200.js.map +1 -1
  59. package/dist/index201.js +265 -215
  60. package/dist/index201.js.map +1 -1
  61. package/dist/index202.js +207 -307
  62. package/dist/index202.js.map +1 -1
  63. package/dist/index203.js +302 -135
  64. package/dist/index203.js.map +1 -1
  65. package/dist/index204.js +140 -271
  66. package/dist/index204.js.map +1 -1
  67. package/dist/index205.js +263 -253
  68. package/dist/index205.js.map +1 -1
  69. package/dist/index206.js +244 -137
  70. package/dist/index206.js.map +1 -1
  71. package/dist/index207.js +100 -238
  72. package/dist/index207.js.map +1 -1
  73. package/dist/index208.js +278 -74
  74. package/dist/index208.js.map +1 -1
  75. package/dist/index209.js +56 -97
  76. package/dist/index209.js.map +1 -1
  77. package/dist/index210.js +142 -47
  78. package/dist/index210.js.map +1 -1
  79. package/dist/index211.js +38 -84
  80. package/dist/index211.js.map +1 -1
  81. package/dist/index212.js +72 -252
  82. package/dist/index212.js.map +1 -1
  83. package/dist/index213.js +274 -26
  84. package/dist/index213.js.map +1 -1
  85. package/dist/index214.js +29 -94
  86. package/dist/index214.js.map +1 -1
  87. package/dist/index215.js +98 -25
  88. package/dist/index215.js.map +1 -1
  89. package/dist/index216.js +20 -565
  90. package/dist/index216.js.map +1 -1
  91. package/dist/index217.js +564 -17
  92. package/dist/index217.js.map +1 -1
  93. package/dist/index218.js +20 -23
  94. package/dist/index218.js.map +1 -1
  95. package/dist/index219.js +20 -95
  96. package/dist/index219.js.map +1 -1
  97. package/dist/index220.js +92 -88
  98. package/dist/index220.js.map +1 -1
  99. package/dist/index221.js +97 -29
  100. package/dist/index221.js.map +1 -1
  101. package/dist/index222.js +24 -470
  102. package/dist/index222.js.map +1 -1
  103. package/dist/index223.js +446 -196
  104. package/dist/index223.js.map +1 -1
  105. package/dist/index224.js +199 -729
  106. package/dist/index224.js.map +1 -1
  107. package/dist/index225.js +750 -61
  108. package/dist/index225.js.map +1 -1
  109. package/dist/index226.js +58 -181
  110. package/dist/index226.js.map +1 -1
  111. package/dist/index227.js +175 -259
  112. package/dist/index227.js.map +1 -1
  113. package/dist/index228.js +246 -172
  114. package/dist/index228.js.map +1 -1
  115. package/dist/index229.js +195 -32
  116. package/dist/index229.js.map +1 -1
  117. package/dist/index230.js +12 -40
  118. package/dist/index230.js.map +1 -1
  119. package/dist/index231.js +23 -26
  120. package/dist/index231.js.map +1 -1
  121. package/dist/index232.js +45 -22
  122. package/dist/index232.js.map +1 -1
  123. package/dist/index233.js +27 -48
  124. package/dist/index233.js.map +1 -1
  125. package/dist/index234.js +52 -26
  126. package/dist/index234.js.map +1 -1
  127. package/dist/index235.js +40 -225
  128. package/dist/index235.js.map +1 -1
  129. package/dist/index236.js +217 -39
  130. package/dist/index236.js.map +1 -1
  131. package/dist/index237.js +50 -0
  132. package/dist/index237.js.map +1 -0
  133. package/dist/styles.css +1 -1
  134. package/dist/wc/AIToolCall.js +218 -0
  135. package/dist/wc/AIToolCall.js.map +1 -0
  136. package/dist/wc/hf-ai-tool-call.js +34 -219
  137. package/dist/wc/hf-ai-tool-call.js.map +1 -1
  138. package/dist/wc/hf-ai-tool-run.js +673 -576
  139. package/dist/wc/hf-ai-tool-run.js.map +1 -1
  140. package/dist/wc/workflow-step-renderer.js +79 -78
  141. package/dist/wc/workflow-step-renderer.js.map +1 -1
  142. package/dist/wc-react/AIToolCall.js +218 -0
  143. package/dist/wc-react/AIToolCall.js.map +1 -0
  144. package/dist/wc-react/hf-ai-tool-call.js +32 -217
  145. package/dist/wc-react/hf-ai-tool-call.js.map +1 -1
  146. package/dist/wc-react/hf-ai-tool-run.js +698 -601
  147. package/dist/wc-react/hf-ai-tool-run.js.map +1 -1
  148. package/dist/wc-react/workflow-step-renderer.js +58 -57
  149. package/dist/wc-react/workflow-step-renderer.js.map +1 -1
  150. package/package.json +1 -1
  151. package/skills/humain-ui/SKILL.md +1 -1
  152. package/skills/humain-ui-wc/SKILL.md +1 -1
  153. package/skills/humain-ui-wc.skill +0 -0
  154. package/skills/humain-ui.skill +0 -0
  155. package/dist/index182.js +0 -143
  156. package/dist/index182.js.map +0 -1
  157. package/dist/wc/wrench.js +0 -10
  158. package/dist/wc/wrench.js.map +0 -1
  159. package/dist/wc-react/wrench.js +0 -10
  160. package/dist/wc-react/wrench.js.map +0 -1
package/dist/index179.js CHANGED
@@ -1,2 +1,134 @@
1
- import { AITable } from "./index178.js";
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 { 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=index180.js.map
1
+ import { AITable } from "./index179.js";
2
+ export { AITable, AITable as default };
@@ -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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"}