@lssm/module.ai-chat 1.41.1 → 1.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/ai-chat.feature.d.ts +12 -0
  4. package/dist/ai-chat.feature.d.ts.map +1 -0
  5. package/dist/ai-chat.feature.js +95 -1
  6. package/dist/ai-chat.feature.js.map +1 -0
  7. package/dist/ai-chat.operations.d.ts +243 -0
  8. package/dist/ai-chat.operations.d.ts.map +1 -0
  9. package/dist/ai-chat.operations.js +174 -0
  10. package/dist/ai-chat.operations.js.map +1 -0
  11. package/dist/context/context-builder.d.ts +57 -0
  12. package/dist/context/context-builder.d.ts.map +1 -0
  13. package/dist/context/context-builder.js +148 -2
  14. package/dist/context/context-builder.js.map +1 -0
  15. package/dist/context/file-operations.d.ts +100 -0
  16. package/dist/context/file-operations.d.ts.map +1 -0
  17. package/dist/context/file-operations.js +175 -1
  18. package/dist/context/file-operations.js.map +1 -0
  19. package/dist/context/index.d.ts +4 -0
  20. package/dist/context/index.js +5 -1
  21. package/dist/context/workspace-context.d.ts +117 -0
  22. package/dist/context/workspace-context.d.ts.map +1 -0
  23. package/dist/context/workspace-context.js +124 -2
  24. package/dist/context/workspace-context.js.map +1 -0
  25. package/dist/core/chat-service.d.ts +73 -0
  26. package/dist/core/chat-service.d.ts.map +1 -0
  27. package/dist/core/chat-service.js +215 -2
  28. package/dist/core/chat-service.js.map +1 -0
  29. package/dist/core/conversation-store.d.ts +74 -0
  30. package/dist/core/conversation-store.d.ts.map +1 -0
  31. package/dist/core/conversation-store.js +109 -1
  32. package/dist/core/conversation-store.js.map +1 -0
  33. package/dist/core/index.d.ts +4 -0
  34. package/dist/core/index.js +4 -1
  35. package/dist/core/message-types.d.ts +150 -0
  36. package/dist/core/message-types.d.ts.map +1 -0
  37. package/dist/events.d.ts +115 -0
  38. package/dist/events.d.ts.map +1 -0
  39. package/dist/events.js +100 -0
  40. package/dist/events.js.map +1 -0
  41. package/dist/index.d.ts +21 -0
  42. package/dist/index.js +23 -1
  43. package/dist/libs/schema/dist/EnumType.js +2 -0
  44. package/dist/libs/schema/dist/FieldType.js +50 -0
  45. package/dist/libs/schema/dist/FieldType.js.map +1 -0
  46. package/dist/libs/schema/dist/ScalarTypeEnum.js +237 -0
  47. package/dist/libs/schema/dist/ScalarTypeEnum.js.map +1 -0
  48. package/dist/libs/schema/dist/SchemaModel.js +40 -0
  49. package/dist/libs/schema/dist/SchemaModel.js.map +1 -0
  50. package/dist/libs/schema/dist/entity/defineEntity.js +1 -0
  51. package/dist/libs/schema/dist/entity/index.js +2 -0
  52. package/dist/libs/schema/dist/entity/types.js +1 -0
  53. package/dist/libs/schema/dist/index.js +6 -0
  54. package/dist/presentation/components/ChatContainer.d.ts +21 -0
  55. package/dist/presentation/components/ChatContainer.d.ts.map +1 -0
  56. package/dist/presentation/components/ChatContainer.js +63 -1
  57. package/dist/presentation/components/ChatContainer.js.map +1 -0
  58. package/dist/presentation/components/ChatInput.d.ts +35 -0
  59. package/dist/presentation/components/ChatInput.d.ts.map +1 -0
  60. package/dist/presentation/components/ChatInput.js +149 -1
  61. package/dist/presentation/components/ChatInput.js.map +1 -0
  62. package/dist/presentation/components/ChatMessage.d.ts +24 -0
  63. package/dist/presentation/components/ChatMessage.d.ts.map +1 -0
  64. package/dist/presentation/components/ChatMessage.js +136 -1
  65. package/dist/presentation/components/ChatMessage.js.map +1 -0
  66. package/dist/presentation/components/CodePreview.d.ts +40 -0
  67. package/dist/presentation/components/CodePreview.d.ts.map +1 -0
  68. package/dist/presentation/components/CodePreview.js +127 -2
  69. package/dist/presentation/components/CodePreview.js.map +1 -0
  70. package/dist/presentation/components/ContextIndicator.d.ts +26 -0
  71. package/dist/presentation/components/ContextIndicator.d.ts.map +1 -0
  72. package/dist/presentation/components/ContextIndicator.js +97 -1
  73. package/dist/presentation/components/ContextIndicator.js.map +1 -0
  74. package/dist/presentation/components/ModelPicker.d.ts +39 -0
  75. package/dist/presentation/components/ModelPicker.d.ts.map +1 -0
  76. package/dist/presentation/components/ModelPicker.js +202 -1
  77. package/dist/presentation/components/ModelPicker.js.map +1 -0
  78. package/dist/presentation/components/index.d.ts +7 -0
  79. package/dist/presentation/components/index.js +8 -1
  80. package/dist/presentation/hooks/index.d.ts +3 -0
  81. package/dist/presentation/hooks/index.js +4 -1
  82. package/dist/presentation/hooks/useChat.d.ts +67 -0
  83. package/dist/presentation/hooks/useChat.d.ts.map +1 -0
  84. package/dist/presentation/hooks/useChat.js +172 -1
  85. package/dist/presentation/hooks/useChat.js.map +1 -0
  86. package/dist/presentation/hooks/useProviders.d.ts +38 -0
  87. package/dist/presentation/hooks/useProviders.d.ts.map +1 -0
  88. package/dist/presentation/hooks/useProviders.js +41 -1
  89. package/dist/presentation/hooks/useProviders.js.map +1 -0
  90. package/dist/presentation/index.d.ts +11 -0
  91. package/dist/presentation/index.js +12 -1
  92. package/dist/providers/chat-utilities.d.ts +15 -0
  93. package/dist/providers/chat-utilities.d.ts.map +1 -0
  94. package/dist/providers/chat-utilities.js +17 -1
  95. package/dist/providers/chat-utilities.js.map +1 -0
  96. package/dist/providers/index.d.ts +3 -0
  97. package/dist/providers/index.js +4 -1
  98. package/dist/schema.d.ts +222 -0
  99. package/dist/schema.d.ts.map +1 -0
  100. package/dist/schema.js +102 -0
  101. package/dist/schema.js.map +1 -0
  102. package/package.json +29 -22
@@ -0,0 +1,237 @@
1
+ import { FieldType } from "./FieldType.js";
2
+ import * as z from "zod";
3
+ import { Kind } from "graphql";
4
+
5
+ //#region ../../libs/schema/dist/ScalarTypeEnum.js
6
+ const localeRegex = /^[A-Za-z]{2}(?:-[A-Za-z0-9]{2,8})*$/;
7
+ const timezoneRegex = /^(?:UTC|[A-Za-z_]+\/[A-Za-z_]+)$/;
8
+ const phoneRegex = /^[+]?\d[\d\s().-]{3,}$/;
9
+ const currencyRegex = /^[A-Z]{3}$/;
10
+ const countryRegex = /^[A-Z]{2}$/;
11
+ const latMin = -90;
12
+ const latMax = 90;
13
+ const lonMin = -180;
14
+ const lonMax = 180;
15
+ /**
16
+ * Factory functions for common scalar FieldTypes with zod/GraphQL/JSON Schema.
17
+ */
18
+ const ScalarTypeEnum = {
19
+ String_unsecure: () => new FieldType({
20
+ name: "String_unsecure",
21
+ description: "Unvalidated string scalar",
22
+ zod: z.string(),
23
+ parseValue: (v) => z.string().parse(v),
24
+ serialize: (v) => String(v),
25
+ parseLiteral: (ast) => {
26
+ if (ast.kind !== Kind.STRING) throw new TypeError("Invalid literal");
27
+ return ast.value;
28
+ },
29
+ jsonSchema: { type: "string" }
30
+ }),
31
+ Int_unsecure: () => new FieldType({
32
+ name: "Int_unsecure",
33
+ description: "Unvalidated integer scalar",
34
+ zod: z.number().int(),
35
+ parseValue: (v) => {
36
+ const num = typeof v === "number" ? v : Number(v);
37
+ return z.number().int().parse(num);
38
+ },
39
+ serialize: (v) => Math.trunc(typeof v === "number" ? v : Number(v)),
40
+ parseLiteral: (ast) => {
41
+ if (ast.kind !== Kind.INT) throw new TypeError("Invalid literal");
42
+ return Number(ast.value);
43
+ },
44
+ jsonSchema: { type: "integer" }
45
+ }),
46
+ Float_unsecure: () => new FieldType({
47
+ name: "Float_unsecure",
48
+ description: "Unvalidated float scalar",
49
+ zod: z.number(),
50
+ parseValue: (v) => {
51
+ const num = typeof v === "number" ? v : Number(v);
52
+ return z.number().parse(num);
53
+ },
54
+ serialize: (v) => Number(v),
55
+ parseLiteral: (ast) => {
56
+ if (ast.kind !== Kind.FLOAT && ast.kind !== Kind.INT) throw new TypeError("Invalid literal");
57
+ return Number(ast.value);
58
+ },
59
+ jsonSchema: { type: "number" }
60
+ }),
61
+ Boolean: () => new FieldType({
62
+ name: "Boolean",
63
+ description: "Unvalidated boolean scalar",
64
+ zod: z.boolean(),
65
+ parseValue: (v) => z.coerce.boolean().parse(v),
66
+ serialize: (v) => Boolean(v),
67
+ parseLiteral: (ast) => {
68
+ if (ast.kind !== Kind.BOOLEAN) throw new TypeError("Invalid literal");
69
+ return ast.value;
70
+ },
71
+ jsonSchema: { type: "boolean" }
72
+ }),
73
+ ID: () => new FieldType({
74
+ name: "ID",
75
+ description: "Unvalidated id scalar",
76
+ zod: z.string(),
77
+ parseValue: (v) => z.string().parse(v),
78
+ serialize: (v) => String(v),
79
+ parseLiteral: (ast) => {
80
+ if (ast.kind !== Kind.STRING) throw new TypeError("Invalid literal");
81
+ return ast.value;
82
+ },
83
+ jsonSchema: { type: "string" }
84
+ }),
85
+ JSON: () => new FieldType({
86
+ name: "JSON",
87
+ zod: z.any(),
88
+ parseValue: (v) => v,
89
+ serialize: (v) => v,
90
+ jsonSchema: {}
91
+ }),
92
+ JSONObject: () => new FieldType({
93
+ name: "JSONObject",
94
+ zod: z.record(z.string(), z.any()),
95
+ parseValue: (v) => z.record(z.string(), z.any()).parse(v),
96
+ serialize: (v) => v ?? {},
97
+ jsonSchema: { type: "object" }
98
+ }),
99
+ Date: () => new FieldType({
100
+ name: "Date",
101
+ zod: z.date(),
102
+ parseValue: (v) => v instanceof Date ? v : new Date(String(v)),
103
+ serialize: (v) => v instanceof Date ? v.toISOString().split("T")[0] : String(v),
104
+ jsonSchema: {
105
+ type: "string",
106
+ format: "date"
107
+ }
108
+ }),
109
+ DateTime: () => new FieldType({
110
+ name: "DateTime",
111
+ zod: z.date(),
112
+ parseValue: (v) => v instanceof Date ? v : new Date(String(v)),
113
+ serialize: (v) => {
114
+ return v instanceof Date ? v.toISOString() : String(v);
115
+ },
116
+ jsonSchema: {
117
+ type: "string",
118
+ format: "date-time"
119
+ }
120
+ }),
121
+ Time: () => new FieldType({
122
+ name: "Time",
123
+ zod: z.string().regex(/^\d{2}:\d{2}(:\d{2})?$/),
124
+ parseValue: (v) => z.string().regex(/^\d{2}:\d{2}(:\d{2})?$/).parse(v),
125
+ serialize: (v) => String(v),
126
+ jsonSchema: {
127
+ type: "string",
128
+ pattern: "^\\d{2}:\\d{2}(:\\d{2})?$"
129
+ }
130
+ }),
131
+ EmailAddress: () => new FieldType({
132
+ name: "EmailAddress",
133
+ zod: z.string().email(),
134
+ parseValue: (v) => z.string().email().parse(v),
135
+ serialize: (v) => String(v),
136
+ jsonSchema: {
137
+ type: "string",
138
+ format: "email"
139
+ }
140
+ }),
141
+ URL: () => new FieldType({
142
+ name: "URL",
143
+ zod: z.string().url(),
144
+ parseValue: (v) => z.string().url().parse(v),
145
+ serialize: (v) => String(v),
146
+ jsonSchema: {
147
+ type: "string",
148
+ format: "uri"
149
+ }
150
+ }),
151
+ PhoneNumber: () => new FieldType({
152
+ name: "PhoneNumber",
153
+ zod: z.string().regex(phoneRegex),
154
+ parseValue: (v) => z.string().regex(phoneRegex).parse(v),
155
+ serialize: (v) => String(v),
156
+ jsonSchema: {
157
+ type: "string",
158
+ pattern: phoneRegex.source
159
+ }
160
+ }),
161
+ NonEmptyString: () => new FieldType({
162
+ name: "NonEmptyString",
163
+ zod: z.string().min(1),
164
+ parseValue: (v) => z.string().min(1).parse(v),
165
+ serialize: (v) => String(v),
166
+ jsonSchema: {
167
+ type: "string",
168
+ minLength: 1
169
+ }
170
+ }),
171
+ Locale: () => new FieldType({
172
+ name: "Locale",
173
+ zod: z.string().regex(localeRegex),
174
+ parseValue: (v) => z.string().regex(localeRegex).parse(v),
175
+ serialize: (v) => String(v),
176
+ jsonSchema: {
177
+ type: "string",
178
+ pattern: localeRegex.source
179
+ }
180
+ }),
181
+ TimeZone: () => new FieldType({
182
+ name: "TimeZone",
183
+ zod: z.string().regex(timezoneRegex),
184
+ parseValue: (v) => z.string().regex(timezoneRegex).parse(v),
185
+ serialize: (v) => String(v),
186
+ jsonSchema: {
187
+ type: "string",
188
+ pattern: timezoneRegex.source
189
+ }
190
+ }),
191
+ Latitude: () => new FieldType({
192
+ name: "Latitude",
193
+ zod: z.number().min(latMin).max(latMax),
194
+ parseValue: (v) => z.coerce.number().min(latMin).max(latMax).parse(v),
195
+ serialize: (v) => Number(v),
196
+ jsonSchema: {
197
+ type: "number",
198
+ minimum: latMin,
199
+ maximum: latMax
200
+ }
201
+ }),
202
+ Longitude: () => new FieldType({
203
+ name: "Longitude",
204
+ zod: z.number().min(lonMin).max(lonMax),
205
+ parseValue: (v) => z.coerce.number().min(lonMin).max(lonMax).parse(v),
206
+ serialize: (v) => Number(v),
207
+ jsonSchema: {
208
+ type: "number",
209
+ minimum: lonMin,
210
+ maximum: lonMax
211
+ }
212
+ }),
213
+ Currency: () => new FieldType({
214
+ name: "Currency",
215
+ zod: z.string().regex(currencyRegex),
216
+ parseValue: (v) => z.string().regex(currencyRegex).parse(v),
217
+ serialize: (v) => String(v),
218
+ jsonSchema: {
219
+ type: "string",
220
+ pattern: currencyRegex.source
221
+ }
222
+ }),
223
+ CountryCode: () => new FieldType({
224
+ name: "CountryCode",
225
+ zod: z.string().regex(countryRegex),
226
+ parseValue: (v) => z.string().regex(countryRegex).parse(v),
227
+ serialize: (v) => String(v),
228
+ jsonSchema: {
229
+ type: "string",
230
+ pattern: countryRegex.source
231
+ }
232
+ })
233
+ };
234
+
235
+ //#endregion
236
+ export { ScalarTypeEnum };
237
+ //# sourceMappingURL=ScalarTypeEnum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScalarTypeEnum.js","names":[],"sources":["../../../../../../libs/schema/dist/ScalarTypeEnum.js"],"sourcesContent":["import { FieldType } from \"./FieldType.js\";\nimport * as z from \"zod\";\nimport { Kind } from \"graphql\";\n\n//#region src/ScalarTypeEnum.ts\nconst localeRegex = /^[A-Za-z]{2}(?:-[A-Za-z0-9]{2,8})*$/;\nconst timezoneRegex = /^(?:UTC|[A-Za-z_]+\\/[A-Za-z_]+)$/;\nconst phoneRegex = /^[+]?\\d[\\d\\s().-]{3,}$/;\nconst currencyRegex = /^[A-Z]{3}$/;\nconst countryRegex = /^[A-Z]{2}$/;\nconst latMin = -90;\nconst latMax = 90;\nconst lonMin = -180;\nconst lonMax = 180;\n/**\n* Factory functions for common scalar FieldTypes with zod/GraphQL/JSON Schema.\n*/\nconst ScalarTypeEnum = {\n\tString_unsecure: () => new FieldType({\n\t\tname: \"String_unsecure\",\n\t\tdescription: \"Unvalidated string scalar\",\n\t\tzod: z.string(),\n\t\tparseValue: (v) => z.string().parse(v),\n\t\tserialize: (v) => String(v),\n\t\tparseLiteral: (ast) => {\n\t\t\tif (ast.kind !== Kind.STRING) throw new TypeError(\"Invalid literal\");\n\t\t\treturn ast.value;\n\t\t},\n\t\tjsonSchema: { type: \"string\" }\n\t}),\n\tInt_unsecure: () => new FieldType({\n\t\tname: \"Int_unsecure\",\n\t\tdescription: \"Unvalidated integer scalar\",\n\t\tzod: z.number().int(),\n\t\tparseValue: (v) => {\n\t\t\tconst num = typeof v === \"number\" ? v : Number(v);\n\t\t\treturn z.number().int().parse(num);\n\t\t},\n\t\tserialize: (v) => Math.trunc(typeof v === \"number\" ? v : Number(v)),\n\t\tparseLiteral: (ast) => {\n\t\t\tif (ast.kind !== Kind.INT) throw new TypeError(\"Invalid literal\");\n\t\t\treturn Number(ast.value);\n\t\t},\n\t\tjsonSchema: { type: \"integer\" }\n\t}),\n\tFloat_unsecure: () => new FieldType({\n\t\tname: \"Float_unsecure\",\n\t\tdescription: \"Unvalidated float scalar\",\n\t\tzod: z.number(),\n\t\tparseValue: (v) => {\n\t\t\tconst num = typeof v === \"number\" ? v : Number(v);\n\t\t\treturn z.number().parse(num);\n\t\t},\n\t\tserialize: (v) => Number(v),\n\t\tparseLiteral: (ast) => {\n\t\t\tif (ast.kind !== Kind.FLOAT && ast.kind !== Kind.INT) throw new TypeError(\"Invalid literal\");\n\t\t\treturn Number(ast.value);\n\t\t},\n\t\tjsonSchema: { type: \"number\" }\n\t}),\n\tBoolean: () => new FieldType({\n\t\tname: \"Boolean\",\n\t\tdescription: \"Unvalidated boolean scalar\",\n\t\tzod: z.boolean(),\n\t\tparseValue: (v) => z.coerce.boolean().parse(v),\n\t\tserialize: (v) => Boolean(v),\n\t\tparseLiteral: (ast) => {\n\t\t\tif (ast.kind !== Kind.BOOLEAN) throw new TypeError(\"Invalid literal\");\n\t\t\treturn ast.value;\n\t\t},\n\t\tjsonSchema: { type: \"boolean\" }\n\t}),\n\tID: () => new FieldType({\n\t\tname: \"ID\",\n\t\tdescription: \"Unvalidated id scalar\",\n\t\tzod: z.string(),\n\t\tparseValue: (v) => z.string().parse(v),\n\t\tserialize: (v) => String(v),\n\t\tparseLiteral: (ast) => {\n\t\t\tif (ast.kind !== Kind.STRING) throw new TypeError(\"Invalid literal\");\n\t\t\treturn ast.value;\n\t\t},\n\t\tjsonSchema: { type: \"string\" }\n\t}),\n\tJSON: () => new FieldType({\n\t\tname: \"JSON\",\n\t\tzod: z.any(),\n\t\tparseValue: (v) => v,\n\t\tserialize: (v) => v,\n\t\tjsonSchema: {}\n\t}),\n\tJSONObject: () => new FieldType({\n\t\tname: \"JSONObject\",\n\t\tzod: z.record(z.string(), z.any()),\n\t\tparseValue: (v) => z.record(z.string(), z.any()).parse(v),\n\t\tserialize: (v) => v ?? {},\n\t\tjsonSchema: { type: \"object\" }\n\t}),\n\tDate: () => new FieldType({\n\t\tname: \"Date\",\n\t\tzod: z.date(),\n\t\tparseValue: (v) => v instanceof Date ? v : new Date(String(v)),\n\t\tserialize: (v) => v instanceof Date ? v.toISOString().split(\"T\")[0] : String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tformat: \"date\"\n\t\t}\n\t}),\n\tDateTime: () => new FieldType({\n\t\tname: \"DateTime\",\n\t\tzod: z.date(),\n\t\tparseValue: (v) => v instanceof Date ? v : new Date(String(v)),\n\t\tserialize: (v) => {\n\t\t\treturn v instanceof Date ? v.toISOString() : String(v);\n\t\t},\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tformat: \"date-time\"\n\t\t}\n\t}),\n\tTime: () => new FieldType({\n\t\tname: \"Time\",\n\t\tzod: z.string().regex(/^\\d{2}:\\d{2}(:\\d{2})?$/),\n\t\tparseValue: (v) => z.string().regex(/^\\d{2}:\\d{2}(:\\d{2})?$/).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: \"^\\\\d{2}:\\\\d{2}(:\\\\d{2})?$\"\n\t\t}\n\t}),\n\tEmailAddress: () => new FieldType({\n\t\tname: \"EmailAddress\",\n\t\tzod: z.string().email(),\n\t\tparseValue: (v) => z.string().email().parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tformat: \"email\"\n\t\t}\n\t}),\n\tURL: () => new FieldType({\n\t\tname: \"URL\",\n\t\tzod: z.string().url(),\n\t\tparseValue: (v) => z.string().url().parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tformat: \"uri\"\n\t\t}\n\t}),\n\tPhoneNumber: () => new FieldType({\n\t\tname: \"PhoneNumber\",\n\t\tzod: z.string().regex(phoneRegex),\n\t\tparseValue: (v) => z.string().regex(phoneRegex).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: phoneRegex.source\n\t\t}\n\t}),\n\tNonEmptyString: () => new FieldType({\n\t\tname: \"NonEmptyString\",\n\t\tzod: z.string().min(1),\n\t\tparseValue: (v) => z.string().min(1).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tminLength: 1\n\t\t}\n\t}),\n\tLocale: () => new FieldType({\n\t\tname: \"Locale\",\n\t\tzod: z.string().regex(localeRegex),\n\t\tparseValue: (v) => z.string().regex(localeRegex).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: localeRegex.source\n\t\t}\n\t}),\n\tTimeZone: () => new FieldType({\n\t\tname: \"TimeZone\",\n\t\tzod: z.string().regex(timezoneRegex),\n\t\tparseValue: (v) => z.string().regex(timezoneRegex).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: timezoneRegex.source\n\t\t}\n\t}),\n\tLatitude: () => new FieldType({\n\t\tname: \"Latitude\",\n\t\tzod: z.number().min(latMin).max(latMax),\n\t\tparseValue: (v) => z.coerce.number().min(latMin).max(latMax).parse(v),\n\t\tserialize: (v) => Number(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"number\",\n\t\t\tminimum: latMin,\n\t\t\tmaximum: latMax\n\t\t}\n\t}),\n\tLongitude: () => new FieldType({\n\t\tname: \"Longitude\",\n\t\tzod: z.number().min(lonMin).max(lonMax),\n\t\tparseValue: (v) => z.coerce.number().min(lonMin).max(lonMax).parse(v),\n\t\tserialize: (v) => Number(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"number\",\n\t\t\tminimum: lonMin,\n\t\t\tmaximum: lonMax\n\t\t}\n\t}),\n\tCurrency: () => new FieldType({\n\t\tname: \"Currency\",\n\t\tzod: z.string().regex(currencyRegex),\n\t\tparseValue: (v) => z.string().regex(currencyRegex).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: currencyRegex.source\n\t\t}\n\t}),\n\tCountryCode: () => new FieldType({\n\t\tname: \"CountryCode\",\n\t\tzod: z.string().regex(countryRegex),\n\t\tparseValue: (v) => z.string().regex(countryRegex).parse(v),\n\t\tserialize: (v) => String(v),\n\t\tjsonSchema: {\n\t\t\ttype: \"string\",\n\t\t\tpattern: countryRegex.source\n\t\t}\n\t})\n};\n\n//#endregion\nexport { ScalarTypeEnum };\n//# sourceMappingURL=ScalarTypeEnum.js.map"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import "./EnumType.js";
2
+ import "./FieldType.js";
3
+ import * as z from "zod";
4
+
5
+ //#region ../../libs/schema/dist/SchemaModel.js
6
+ /**
7
+ * Named object model built from FieldType/EnumType/SchemaModel fields.
8
+ * Provides zod and GraphQL input helpers, and supports arrays/optional fields.
9
+ */
10
+ var SchemaModel = class {
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Build a typed ZodObject from the model fields, preserving each field's
16
+ * Zod schema and optionality at the type level when possible.
17
+ */
18
+ getZod() {
19
+ const shape = Object.entries(this.config.fields).reduce((acc, [key, def]) => {
20
+ const base = def.type.getZod();
21
+ const withArray = def.isArray ? z.array(base) : base;
22
+ acc[key] = def.isOptional ? withArray.optional() : withArray;
23
+ return acc;
24
+ }, {});
25
+ return z.object(shape);
26
+ }
27
+ /** Input object name for GraphQL builder adapters. */
28
+ getPothosInput() {
29
+ return this.config.name;
30
+ }
31
+ };
32
+ /**
33
+ * Helper to define a SchemaModel with type inference.
34
+ * Equivalent to `new SchemaModel(config)` but with better ergonomics.
35
+ */
36
+ const defineSchemaModel = (config) => new SchemaModel(config);
37
+
38
+ //#endregion
39
+ export { SchemaModel, defineSchemaModel };
40
+ //# sourceMappingURL=SchemaModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaModel.js","names":[],"sources":["../../../../../../libs/schema/dist/SchemaModel.js"],"sourcesContent":["import \"./EnumType.js\";\nimport \"./FieldType.js\";\nimport * as z from \"zod\";\n\n//#region src/SchemaModel.ts\n/**\n* Named object model built from FieldType/EnumType/SchemaModel fields.\n* Provides zod and GraphQL input helpers, and supports arrays/optional fields.\n*/\nvar SchemaModel = class {\n\tconstructor(config) {\n\t\tthis.config = config;\n\t}\n\t/**\n\t* Build a typed ZodObject from the model fields, preserving each field's\n\t* Zod schema and optionality at the type level when possible.\n\t*/\n\tgetZod() {\n\t\tconst shape = Object.entries(this.config.fields).reduce((acc, [key, def]) => {\n\t\t\tconst base = def.type.getZod();\n\t\t\tconst withArray = def.isArray ? z.array(base) : base;\n\t\t\tacc[key] = def.isOptional ? withArray.optional() : withArray;\n\t\t\treturn acc;\n\t\t}, {});\n\t\treturn z.object(shape);\n\t}\n\t/** Input object name for GraphQL builder adapters. */\n\tgetPothosInput() {\n\t\treturn this.config.name;\n\t}\n};\n/**\n* Helper to define a SchemaModel with type inference.\n* Equivalent to `new SchemaModel(config)` but with better ergonomics.\n*/\nconst defineSchemaModel = (config) => new SchemaModel(config);\n\n//#endregion\nexport { SchemaModel, defineSchemaModel };\n//# sourceMappingURL=SchemaModel.js.map"],"mappings":";;;;;;;;;AASA,IAAI,cAAc,MAAM;CACvB,YAAY,QAAQ;AACnB,OAAK,SAAS;;;;;;CAMf,SAAS;EACR,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,OAAO,CAAC,QAAQ,KAAK,CAAC,KAAK,SAAS;GAC5E,MAAM,OAAO,IAAI,KAAK,QAAQ;GAC9B,MAAM,YAAY,IAAI,UAAU,EAAE,MAAM,KAAK,GAAG;AAChD,OAAI,OAAO,IAAI,aAAa,UAAU,UAAU,GAAG;AACnD,UAAO;KACL,EAAE,CAAC;AACN,SAAO,EAAE,OAAO,MAAM;;;CAGvB,iBAAiB;AAChB,SAAO,KAAK,OAAO;;;;;;;AAOrB,MAAM,qBAAqB,WAAW,IAAI,YAAY,OAAO"}
@@ -0,0 +1 @@
1
+ import "zod";
@@ -0,0 +1,2 @@
1
+ import "./defineEntity.js";
2
+ import "./types.js";
@@ -0,0 +1 @@
1
+ import "zod";
@@ -0,0 +1,6 @@
1
+ import "./EnumType.js";
2
+ import { FieldType } from "./FieldType.js";
3
+ import { ScalarTypeEnum } from "./ScalarTypeEnum.js";
4
+ import { SchemaModel, defineSchemaModel } from "./SchemaModel.js";
5
+ import "./entity/defineEntity.js";
6
+ import "./entity/index.js";
@@ -0,0 +1,21 @@
1
+ import * as React from "react";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+
4
+ //#region src/presentation/components/ChatContainer.d.ts
5
+ interface ChatContainerProps {
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ /** Show scroll-to-bottom button when scrolled up */
9
+ showScrollButton?: boolean;
10
+ }
11
+ /**
12
+ * Container component for chat messages with scrolling
13
+ */
14
+ declare function ChatContainer({
15
+ children,
16
+ className,
17
+ showScrollButton
18
+ }: ChatContainerProps): react_jsx_runtime0.JSX.Element;
19
+ //#endregion
20
+ export { ChatContainer };
21
+ //# sourceMappingURL=ChatContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatContainer.d.ts","names":[],"sources":["../../../src/presentation/components/ChatContainer.tsx"],"sourcesContent":[],"mappings":";;;;UAMiB,kBAAA;YACL,KAAA,CAAM;;EADD;EAUD,gBAAa,CAAA,EAAA,OAAA;;;;;AAIR,iBAJL,aAAA,CAIK;EAAA,QAAA;EAAA,SAAA;EAAA;AAAA,CAAA,EAAlB,kBAAkB,CAAA,EAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1 +1,63 @@
1
- "use client";import*as e from"react";import{ScrollArea as t}from"@lssm/lib.ui-kit-web/ui/scroll-area";import{cn as n}from"@lssm/lib.ui-kit-web/ui/utils";import{jsx as r,jsxs as i}from"react/jsx-runtime";function a({children:a,className:o,showScrollButton:s=!0}){let c=e.useRef(null),[l,u]=e.useState(!1);e.useEffect(()=>{let e=c.current;e&&e.scrollHeight-e.scrollTop<=e.clientHeight+100&&(e.scrollTop=e.scrollHeight)},[a]);let d=e.useCallback(e=>{let t=e.currentTarget;u(!(t.scrollHeight-t.scrollTop<=t.clientHeight+100))},[]),f=e.useCallback(()=>{let e=c.current;e&&e.scrollTo({top:e.scrollHeight,behavior:`smooth`})},[]);return i(`div`,{className:n(`relative flex flex-1 flex-col`,o),children:[r(t,{ref:c,className:`flex-1`,onScroll:d,children:r(`div`,{className:`flex flex-col gap-4 p-4`,children:a})}),s&&l&&i(`button`,{onClick:f,className:n(`absolute bottom-4 left-1/2 -translate-x-1/2`,`bg-primary text-primary-foreground`,`rounded-full px-3 py-1.5 text-sm font-medium shadow-lg`,`hover:bg-primary/90 transition-colors`,`flex items-center gap-1.5`),"aria-label":`Scroll to bottom`,children:[r(`svg`,{xmlns:`http://www.w3.org/2000/svg`,width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:r(`path`,{d:`m6 9 6 6 6-6`})}),`New messages`]})]})}export{a as ChatContainer};
1
+ 'use client';
2
+
3
+ import * as React from "react";
4
+ import { ScrollArea } from "@lssm/lib.ui-kit-web/ui/scroll-area";
5
+ import { cn } from "@lssm/lib.ui-kit-web/ui/utils";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+
8
+ //#region src/presentation/components/ChatContainer.tsx
9
+ /**
10
+ * Container component for chat messages with scrolling
11
+ */
12
+ function ChatContainer({ children, className, showScrollButton = true }) {
13
+ const scrollRef = React.useRef(null);
14
+ const [showScrollDown, setShowScrollDown] = React.useState(false);
15
+ React.useEffect(() => {
16
+ const container = scrollRef.current;
17
+ if (!container) return;
18
+ if (container.scrollHeight - container.scrollTop <= container.clientHeight + 100) container.scrollTop = container.scrollHeight;
19
+ }, [children]);
20
+ const handleScroll = React.useCallback((event) => {
21
+ const container = event.currentTarget;
22
+ setShowScrollDown(!(container.scrollHeight - container.scrollTop <= container.clientHeight + 100));
23
+ }, []);
24
+ const scrollToBottom = React.useCallback(() => {
25
+ const container = scrollRef.current;
26
+ if (container) container.scrollTo({
27
+ top: container.scrollHeight,
28
+ behavior: "smooth"
29
+ });
30
+ }, []);
31
+ return /* @__PURE__ */ jsxs("div", {
32
+ className: cn("relative flex flex-1 flex-col", className),
33
+ children: [/* @__PURE__ */ jsx(ScrollArea, {
34
+ ref: scrollRef,
35
+ className: "flex-1",
36
+ onScroll: handleScroll,
37
+ children: /* @__PURE__ */ jsx("div", {
38
+ className: "flex flex-col gap-4 p-4",
39
+ children
40
+ })
41
+ }), showScrollButton && showScrollDown && /* @__PURE__ */ jsxs("button", {
42
+ onClick: scrollToBottom,
43
+ className: cn("absolute bottom-4 left-1/2 -translate-x-1/2", "bg-primary text-primary-foreground", "rounded-full px-3 py-1.5 text-sm font-medium shadow-lg", "hover:bg-primary/90 transition-colors", "flex items-center gap-1.5"),
44
+ "aria-label": "Scroll to bottom",
45
+ children: [/* @__PURE__ */ jsx("svg", {
46
+ xmlns: "http://www.w3.org/2000/svg",
47
+ width: "16",
48
+ height: "16",
49
+ viewBox: "0 0 24 24",
50
+ fill: "none",
51
+ stroke: "currentColor",
52
+ strokeWidth: "2",
53
+ strokeLinecap: "round",
54
+ strokeLinejoin: "round",
55
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
56
+ }), "New messages"]
57
+ })]
58
+ });
59
+ }
60
+
61
+ //#endregion
62
+ export { ChatContainer };
63
+ //# sourceMappingURL=ChatContainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatContainer.js","names":[],"sources":["../../../src/presentation/components/ChatContainer.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ScrollArea } from '@lssm/lib.ui-kit-web/ui/scroll-area';\nimport { cn } from '@lssm/lib.ui-kit-web/ui/utils';\n\nexport interface ChatContainerProps {\n children: React.ReactNode;\n className?: string;\n /** Show scroll-to-bottom button when scrolled up */\n showScrollButton?: boolean;\n}\n\n/**\n * Container component for chat messages with scrolling\n */\nexport function ChatContainer({\n children,\n className,\n showScrollButton = true,\n}: ChatContainerProps) {\n const scrollRef = React.useRef<HTMLDivElement>(null);\n const [showScrollDown, setShowScrollDown] = React.useState(false);\n\n // Auto-scroll to bottom when children change\n React.useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n\n // Check if user has scrolled up\n const isAtBottom =\n container.scrollHeight - container.scrollTop <=\n container.clientHeight + 100;\n\n if (isAtBottom) {\n container.scrollTop = container.scrollHeight;\n }\n }, [children]);\n\n // Track scroll position for scroll-to-bottom button\n const handleScroll = React.useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n const container = event.currentTarget;\n const isAtBottom =\n container.scrollHeight - container.scrollTop <=\n container.clientHeight + 100;\n setShowScrollDown(!isAtBottom);\n },\n []\n );\n\n const scrollToBottom = React.useCallback(() => {\n const container = scrollRef.current;\n if (container) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'smooth',\n });\n }\n }, []);\n\n return (\n <div className={cn('relative flex flex-1 flex-col', className)}>\n <ScrollArea ref={scrollRef} className=\"flex-1\" onScroll={handleScroll}>\n <div className=\"flex flex-col gap-4 p-4\">{children}</div>\n </ScrollArea>\n\n {showScrollButton && showScrollDown && (\n <button\n onClick={scrollToBottom}\n className={cn(\n 'absolute bottom-4 left-1/2 -translate-x-1/2',\n 'bg-primary text-primary-foreground',\n 'rounded-full px-3 py-1.5 text-sm font-medium shadow-lg',\n 'hover:bg-primary/90 transition-colors',\n 'flex items-center gap-1.5'\n )}\n aria-label=\"Scroll to bottom\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n New messages\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAAgB,cAAc,EAC5B,UACA,WACA,mBAAmB,QACE;CACrB,MAAM,YAAY,MAAM,OAAuB,KAAK;CACpD,MAAM,CAAC,gBAAgB,qBAAqB,MAAM,SAAS,MAAM;AAGjE,OAAM,gBAAgB;EACpB,MAAM,YAAY,UAAU;AAC5B,MAAI,CAAC,UAAW;AAOhB,MAHE,UAAU,eAAe,UAAU,aACnC,UAAU,eAAe,IAGzB,WAAU,YAAY,UAAU;IAEjC,CAAC,SAAS,CAAC;CAGd,MAAM,eAAe,MAAM,aACxB,UAAyC;EACxC,MAAM,YAAY,MAAM;AAIxB,oBAAkB,EAFhB,UAAU,eAAe,UAAU,aACnC,UAAU,eAAe,KACG;IAEhC,EAAE,CACH;CAED,MAAM,iBAAiB,MAAM,kBAAkB;EAC7C,MAAM,YAAY,UAAU;AAC5B,MAAI,UACF,WAAU,SAAS;GACjB,KAAK,UAAU;GACf,UAAU;GACX,CAAC;IAEH,EAAE,CAAC;AAEN,QACE,qBAAC;EAAI,WAAW,GAAG,iCAAiC,UAAU;aAC5D,oBAAC;GAAW,KAAK;GAAW,WAAU;GAAS,UAAU;aACvD,oBAAC;IAAI,WAAU;IAA2B;KAAe;IAC9C,EAEZ,oBAAoB,kBACnB,qBAAC;GACC,SAAS;GACT,WAAW,GACT,+CACA,sCACA,0DACA,yCACA,4BACD;GACD,cAAW;cAEX,oBAAC;IACC,OAAM;IACN,OAAM;IACN,QAAO;IACP,SAAQ;IACR,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,gBAAe;cAEf,oBAAC,UAAK,GAAE,iBAAiB;KACrB;IAEC;GAEP"}
@@ -0,0 +1,35 @@
1
+ import { ChatAttachment } from "../../core/message-types.js";
2
+ import * as react_jsx_runtime2 from "react/jsx-runtime";
3
+
4
+ //#region src/presentation/components/ChatInput.d.ts
5
+ interface ChatInputProps {
6
+ /** Called when a message is sent */
7
+ onSend: (content: string, attachments?: ChatAttachment[]) => void;
8
+ /** Whether input is disabled (e.g., during streaming) */
9
+ disabled?: boolean;
10
+ /** Whether currently loading/streaming */
11
+ isLoading?: boolean;
12
+ /** Placeholder text */
13
+ placeholder?: string;
14
+ /** Additional class name */
15
+ className?: string;
16
+ /** Show attachment button */
17
+ showAttachments?: boolean;
18
+ /** Max attachments allowed */
19
+ maxAttachments?: number;
20
+ }
21
+ /**
22
+ * Chat input component with attachment support
23
+ */
24
+ declare function ChatInput({
25
+ onSend,
26
+ disabled,
27
+ isLoading,
28
+ placeholder,
29
+ className,
30
+ showAttachments,
31
+ maxAttachments
32
+ }: ChatInputProps): react_jsx_runtime2.JSX.Element;
33
+ //#endregion
34
+ export { ChatInput };
35
+ //# sourceMappingURL=ChatInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInput.d.ts","names":[],"sources":["../../../src/presentation/components/ChatInput.tsx"],"sourcesContent":[],"mappings":";;;;UASiB,cAAA;;0CAEyB;EAFzB;EAoBD,QAAA,CAAA,EAAA,OAAS;EACvB;EACA,SAAA,CAAA,EAAA,OAAA;EACA;EACA,WAAA,CAAA,EAAA,MAAA;EACA;EACA,SAAA,CAAA,EAAA,MAAA;EACA;EACC,eAAA,CAAA,EAAA,OAAA;EAAc;EAAA,cAAA,CAAA,EAAA,MAAA;;;;;iBARD,SAAA;;;;;;;;GAQb,iBAAc,kBAAA,CAAA,GAAA,CAAA"}
@@ -1 +1,149 @@
1
- "use client";import*as e from"react";import{cn as t}from"@lssm/lib.ui-kit-web/ui/utils";import{Fragment as n,jsx as r,jsxs as i}from"react/jsx-runtime";import{Code as a,FileText as o,Loader2 as s,Paperclip as c,Send as l,X as u}from"lucide-react";import{Button as d,Textarea as f}from"@lssm/lib.design-system";function p({onSend:p,disabled:m=!1,isLoading:h=!1,placeholder:g=`Type a message...`,className:_,showAttachments:v=!0,maxAttachments:y=5}){let[b,x]=e.useState(``),[S,C]=e.useState([]),w=e.useRef(null),T=e.useRef(null),E=b.trim().length>0||S.length>0,D=e.useCallback(e=>{e?.preventDefault(),!(!E||m||h)&&(p(b.trim(),S.length>0?S:void 0),x(``),C([]),w.current?.focus())},[E,b,S,m,h,p]),O=e.useCallback(e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),D())},[D]),k=e.useCallback(async e=>{let t=e.target.files;if(!t)return;let n=[];for(let e of Array.from(t)){if(S.length+n.length>=y)break;let t=await e.text(),r=e.name.split(`.`).pop()?.toLowerCase()??``,i=[`ts`,`tsx`,`js`,`jsx`,`py`,`go`,`rs`,`java`].includes(r);n.push({id:`att_${Date.now()}_${Math.random().toString(36).slice(2,9)}`,type:i?`code`:`file`,name:e.name,content:t,mimeType:e.type,size:e.size})}C(e=>[...e,...n]),e.target.value=``},[S.length,y]),A=e.useCallback(e=>{C(t=>t.filter(t=>t.id!==e))},[]);return i(`div`,{className:t(`flex flex-col gap-2`,_),children:[S.length>0&&r(`div`,{className:`flex flex-wrap gap-2`,children:S.map(e=>i(`div`,{className:t(`flex items-center gap-1.5 rounded-md px-2 py-1`,`bg-muted text-muted-foreground text-sm`),children:[e.type===`code`?r(a,{className:`h-3.5 w-3.5`}):r(o,{className:`h-3.5 w-3.5`}),r(`span`,{className:`max-w-[150px] truncate`,children:e.name}),r(`button`,{type:`button`,onClick:()=>A(e.id),className:`hover:text-foreground`,"aria-label":`Remove ${e.name}`,children:r(u,{className:`h-3.5 w-3.5`})})]},e.id))}),i(`form`,{onSubmit:D,className:`flex items-end gap-2`,children:[v&&i(n,{children:[r(`input`,{ref:T,type:`file`,multiple:!0,accept:`.ts,.tsx,.js,.jsx,.json,.md,.txt,.py,.go,.rs,.java,.yaml,.yml`,onChange:k,className:`hidden`,"aria-label":`Attach files`}),r(d,{type:`button`,variant:`ghost`,size:`sm`,onPress:()=>T.current?.click(),disabled:m||S.length>=y,"aria-label":`Attach files`,children:r(c,{className:`h-4 w-4`})})]}),r(`div`,{className:`relative flex-1`,children:r(f,{value:b,onChange:e=>x(e.target.value),onKeyDown:O,placeholder:g,disabled:m,className:t(`min-h-[44px] max-h-[200px] resize-none pr-12`,`focus-visible:ring-1`),rows:1,"aria-label":`Chat message`})}),r(d,{type:`submit`,disabled:!E||m||h,size:`sm`,"aria-label":h?`Sending...`:`Send message`,children:h?r(s,{className:`h-4 w-4 animate-spin`}):r(l,{className:`h-4 w-4`})})]}),r(`p`,{className:`text-muted-foreground text-xs`,children:`Press Enter to send, Shift+Enter for new line`})]})}export{p as ChatInput};
1
+ 'use client';
2
+
3
+ import * as React from "react";
4
+ import { cn } from "@lssm/lib.ui-kit-web/ui/utils";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { Code, FileText, Loader2, Paperclip, Send, X } from "lucide-react";
7
+ import { Button, Textarea } from "@lssm/lib.design-system";
8
+
9
+ //#region src/presentation/components/ChatInput.tsx
10
+ /**
11
+ * Chat input component with attachment support
12
+ */
13
+ function ChatInput({ onSend, disabled = false, isLoading = false, placeholder = "Type a message...", className, showAttachments = true, maxAttachments = 5 }) {
14
+ const [content, setContent] = React.useState("");
15
+ const [attachments, setAttachments] = React.useState([]);
16
+ const textareaRef = React.useRef(null);
17
+ const fileInputRef = React.useRef(null);
18
+ const canSend = content.trim().length > 0 || attachments.length > 0;
19
+ const handleSubmit = React.useCallback((e) => {
20
+ e?.preventDefault();
21
+ if (!canSend || disabled || isLoading) return;
22
+ onSend(content.trim(), attachments.length > 0 ? attachments : void 0);
23
+ setContent("");
24
+ setAttachments([]);
25
+ textareaRef.current?.focus();
26
+ }, [
27
+ canSend,
28
+ content,
29
+ attachments,
30
+ disabled,
31
+ isLoading,
32
+ onSend
33
+ ]);
34
+ const handleKeyDown = React.useCallback((e) => {
35
+ if (e.key === "Enter" && !e.shiftKey) {
36
+ e.preventDefault();
37
+ handleSubmit();
38
+ }
39
+ }, [handleSubmit]);
40
+ const handleFileSelect = React.useCallback(async (e) => {
41
+ const files = e.target.files;
42
+ if (!files) return;
43
+ const newAttachments = [];
44
+ for (const file of Array.from(files)) {
45
+ if (attachments.length + newAttachments.length >= maxAttachments) break;
46
+ const content$1 = await file.text();
47
+ const extension = file.name.split(".").pop()?.toLowerCase() ?? "";
48
+ const isCode = [
49
+ "ts",
50
+ "tsx",
51
+ "js",
52
+ "jsx",
53
+ "py",
54
+ "go",
55
+ "rs",
56
+ "java"
57
+ ].includes(extension);
58
+ newAttachments.push({
59
+ id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
60
+ type: isCode ? "code" : "file",
61
+ name: file.name,
62
+ content: content$1,
63
+ mimeType: file.type,
64
+ size: file.size
65
+ });
66
+ }
67
+ setAttachments((prev) => [...prev, ...newAttachments]);
68
+ e.target.value = "";
69
+ }, [attachments.length, maxAttachments]);
70
+ const removeAttachment = React.useCallback((id) => {
71
+ setAttachments((prev) => prev.filter((a) => a.id !== id));
72
+ }, []);
73
+ return /* @__PURE__ */ jsxs("div", {
74
+ className: cn("flex flex-col gap-2", className),
75
+ children: [
76
+ attachments.length > 0 && /* @__PURE__ */ jsx("div", {
77
+ className: "flex flex-wrap gap-2",
78
+ children: attachments.map((attachment) => /* @__PURE__ */ jsxs("div", {
79
+ className: cn("flex items-center gap-1.5 rounded-md px-2 py-1", "bg-muted text-muted-foreground text-sm"),
80
+ children: [
81
+ attachment.type === "code" ? /* @__PURE__ */ jsx(Code, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5" }),
82
+ /* @__PURE__ */ jsx("span", {
83
+ className: "max-w-[150px] truncate",
84
+ children: attachment.name
85
+ }),
86
+ /* @__PURE__ */ jsx("button", {
87
+ type: "button",
88
+ onClick: () => removeAttachment(attachment.id),
89
+ className: "hover:text-foreground",
90
+ "aria-label": `Remove ${attachment.name}`,
91
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
92
+ })
93
+ ]
94
+ }, attachment.id))
95
+ }),
96
+ /* @__PURE__ */ jsxs("form", {
97
+ onSubmit: handleSubmit,
98
+ className: "flex items-end gap-2",
99
+ children: [
100
+ showAttachments && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
101
+ ref: fileInputRef,
102
+ type: "file",
103
+ multiple: true,
104
+ accept: ".ts,.tsx,.js,.jsx,.json,.md,.txt,.py,.go,.rs,.java,.yaml,.yml",
105
+ onChange: handleFileSelect,
106
+ className: "hidden",
107
+ "aria-label": "Attach files"
108
+ }), /* @__PURE__ */ jsx(Button, {
109
+ type: "button",
110
+ variant: "ghost",
111
+ size: "sm",
112
+ onPress: () => fileInputRef.current?.click(),
113
+ disabled: disabled || attachments.length >= maxAttachments,
114
+ "aria-label": "Attach files",
115
+ children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
116
+ })] }),
117
+ /* @__PURE__ */ jsx("div", {
118
+ className: "relative flex-1",
119
+ children: /* @__PURE__ */ jsx(Textarea, {
120
+ value: content,
121
+ onChange: (e) => setContent(e.target.value),
122
+ onKeyDown: handleKeyDown,
123
+ placeholder,
124
+ disabled,
125
+ className: cn("max-h-[200px] min-h-[44px] resize-none pr-12", "focus-visible:ring-1"),
126
+ rows: 1,
127
+ "aria-label": "Chat message"
128
+ })
129
+ }),
130
+ /* @__PURE__ */ jsx(Button, {
131
+ type: "submit",
132
+ disabled: !canSend || disabled || isLoading,
133
+ size: "sm",
134
+ "aria-label": isLoading ? "Sending..." : "Send message",
135
+ children: isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Send, { className: "h-4 w-4" })
136
+ })
137
+ ]
138
+ }),
139
+ /* @__PURE__ */ jsx("p", {
140
+ className: "text-muted-foreground text-xs",
141
+ children: "Press Enter to send, Shift+Enter for new line"
142
+ })
143
+ ]
144
+ });
145
+ }
146
+
147
+ //#endregion
148
+ export { ChatInput };
149
+ //# sourceMappingURL=ChatInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInput.js","names":["newAttachments: ChatAttachment[]","content"],"sources":["../../../src/presentation/components/ChatInput.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '@lssm/lib.ui-kit-web/ui/utils';\nimport { Textarea } from '@lssm/lib.design-system';\nimport { Button } from '@lssm/lib.design-system';\nimport { Send, Paperclip, X, Loader2, FileText, Code } from 'lucide-react';\nimport type { ChatAttachment } from '../../core/message-types';\n\nexport interface ChatInputProps {\n /** Called when a message is sent */\n onSend: (content: string, attachments?: ChatAttachment[]) => void;\n /** Whether input is disabled (e.g., during streaming) */\n disabled?: boolean;\n /** Whether currently loading/streaming */\n isLoading?: boolean;\n /** Placeholder text */\n placeholder?: string;\n /** Additional class name */\n className?: string;\n /** Show attachment button */\n showAttachments?: boolean;\n /** Max attachments allowed */\n maxAttachments?: number;\n}\n\n/**\n * Chat input component with attachment support\n */\nexport function ChatInput({\n onSend,\n disabled = false,\n isLoading = false,\n placeholder = 'Type a message...',\n className,\n showAttachments = true,\n maxAttachments = 5,\n}: ChatInputProps) {\n const [content, setContent] = React.useState('');\n const [attachments, setAttachments] = React.useState<ChatAttachment[]>([]);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const fileInputRef = React.useRef<HTMLInputElement>(null);\n\n const canSend = content.trim().length > 0 || attachments.length > 0;\n\n const handleSubmit = React.useCallback(\n (e?: React.FormEvent) => {\n e?.preventDefault();\n if (!canSend || disabled || isLoading) return;\n\n onSend(content.trim(), attachments.length > 0 ? attachments : undefined);\n setContent('');\n setAttachments([]);\n\n // Focus back on textarea\n textareaRef.current?.focus();\n },\n [canSend, content, attachments, disabled, isLoading, onSend]\n );\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n // Submit on Enter (without Shift)\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n },\n [handleSubmit]\n );\n\n const handleFileSelect = React.useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files) return;\n\n const newAttachments: ChatAttachment[] = [];\n\n for (const file of Array.from(files)) {\n if (attachments.length + newAttachments.length >= maxAttachments) break;\n\n const content = await file.text();\n const extension = file.name.split('.').pop()?.toLowerCase() ?? '';\n const isCode = [\n 'ts',\n 'tsx',\n 'js',\n 'jsx',\n 'py',\n 'go',\n 'rs',\n 'java',\n ].includes(extension);\n\n newAttachments.push({\n id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,\n type: isCode ? 'code' : 'file',\n name: file.name,\n content,\n mimeType: file.type,\n size: file.size,\n });\n }\n\n setAttachments((prev) => [...prev, ...newAttachments]);\n\n // Reset file input\n e.target.value = '';\n },\n [attachments.length, maxAttachments]\n );\n\n const removeAttachment = React.useCallback((id: string) => {\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n }, []);\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {/* Attachments preview */}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {attachments.map((attachment) => (\n <div\n key={attachment.id}\n className={cn(\n 'flex items-center gap-1.5 rounded-md px-2 py-1',\n 'bg-muted text-muted-foreground text-sm'\n )}\n >\n {attachment.type === 'code' ? (\n <Code className=\"h-3.5 w-3.5\" />\n ) : (\n <FileText className=\"h-3.5 w-3.5\" />\n )}\n <span className=\"max-w-[150px] truncate\">{attachment.name}</span>\n <button\n type=\"button\"\n onClick={() => removeAttachment(attachment.id)}\n className=\"hover:text-foreground\"\n aria-label={`Remove ${attachment.name}`}\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Input form */}\n <form onSubmit={handleSubmit} className=\"flex items-end gap-2\">\n {/* Attachment button */}\n {showAttachments && (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept=\".ts,.tsx,.js,.jsx,.json,.md,.txt,.py,.go,.rs,.java,.yaml,.yml\"\n onChange={handleFileSelect}\n className=\"hidden\"\n aria-label=\"Attach files\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onPress={() => fileInputRef.current?.click()}\n disabled={disabled || attachments.length >= maxAttachments}\n aria-label=\"Attach files\"\n >\n <Paperclip className=\"h-4 w-4\" />\n </Button>\n </>\n )}\n\n {/* Text input */}\n <div className=\"relative flex-1\">\n <Textarea\n value={content}\n onChange={(e) => setContent(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n className={cn(\n 'max-h-[200px] min-h-[44px] resize-none pr-12',\n 'focus-visible:ring-1'\n )}\n rows={1}\n aria-label=\"Chat message\"\n />\n </div>\n\n {/* Send button */}\n <Button\n type=\"submit\"\n disabled={!canSend || disabled || isLoading}\n size=\"sm\"\n aria-label={isLoading ? 'Sending...' : 'Send message'}\n >\n {isLoading ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Send className=\"h-4 w-4\" />\n )}\n </Button>\n </form>\n\n {/* Helper text */}\n <p className=\"text-muted-foreground text-xs\">\n Press Enter to send, Shift+Enter for new line\n </p>\n </div>\n );\n}\n"],"mappings":"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"}