@meshagent/meshagent-tailwind 0.39.8 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/{ChatBotView.js → chat/chat-bot-view.js} +37 -22
  3. package/dist/cjs/{chat-hooks.d.ts → chat/chat-hooks.d.ts} +5 -1
  4. package/dist/cjs/{chat-hooks.js → chat/chat-hooks.js} +12 -2
  5. package/dist/cjs/{ChatInput.js → chat/chat-input.js} +9 -9
  6. package/dist/cjs/chat/chat-thread.d.ts +12 -0
  7. package/dist/cjs/{ChatThread.js → chat/chat-thread.js} +75 -28
  8. package/dist/cjs/{ChatTypingIndicator.js → chat/chat-typing-indicator.js} +4 -4
  9. package/dist/{esm → cjs/chat}/conversation-descriptor.d.ts +7 -1
  10. package/dist/cjs/{conversation-descriptor.js → chat/conversation-descriptor.js} +41 -7
  11. package/dist/cjs/chat/dataset-chat-thread.d.ts +13 -0
  12. package/dist/cjs/chat/dataset-chat-thread.js +1840 -0
  13. package/dist/cjs/{FileUploader.js → chat/file-uploader.js} +4 -4
  14. package/dist/cjs/{multi-thread-view.js → chat/multi-thread-view.js} +8 -3
  15. package/dist/cjs/chat/new-chat-thread.d.ts +17 -0
  16. package/dist/cjs/{Chat.js → chat/new-chat-thread.js} +43 -168
  17. package/dist/cjs/{UploadPill.js → chat/upload-pill.js} +5 -5
  18. package/dist/cjs/file-preview/file-preview.d.ts +34 -0
  19. package/dist/cjs/file-preview/file-preview.js +329 -0
  20. package/dist/cjs/forms/email-address.d.ts +10 -0
  21. package/dist/cjs/forms/email-address.js +105 -0
  22. package/dist/cjs/forms/form.d.ts +27 -0
  23. package/dist/cjs/forms/form.js +200 -0
  24. package/dist/cjs/forms/multi-select-autocomplete.d.ts +35 -0
  25. package/dist/cjs/forms/multi-select-autocomplete.js +294 -0
  26. package/dist/cjs/forms/select-users-dialog.d.ts +20 -0
  27. package/dist/cjs/forms/select-users-dialog.js +145 -0
  28. package/dist/cjs/forms/select-users.d.ts +16 -0
  29. package/dist/cjs/forms/select-users.js +117 -0
  30. package/dist/cjs/index.d.ts +19 -11
  31. package/dist/cjs/index.js +19 -11
  32. package/dist/cjs/meetings/audio-visualization.d.ts +7 -0
  33. package/dist/cjs/meetings/audio-visualization.js +74 -0
  34. package/dist/cjs/meetings/controls.d.ts +19 -0
  35. package/dist/cjs/meetings/controls.js +300 -0
  36. package/dist/cjs/meetings/meeting-scope.d.ts +83 -0
  37. package/dist/cjs/meetings/meeting-scope.js +309 -0
  38. package/dist/cjs/meetings/meetings.d.ts +5 -0
  39. package/dist/cjs/meetings/meetings.js +22 -0
  40. package/dist/cjs/meetings/participants.d.ts +13 -0
  41. package/dist/cjs/meetings/participants.js +154 -0
  42. package/dist/cjs/meetings/wake-lock.d.ts +4 -0
  43. package/dist/cjs/meetings/wake-lock.js +55 -0
  44. package/dist/esm/{ChatBotView.js → chat/chat-bot-view.js} +34 -19
  45. package/dist/esm/{chat-hooks.d.ts → chat/chat-hooks.d.ts} +5 -1
  46. package/dist/esm/{chat-hooks.js → chat/chat-hooks.js} +12 -2
  47. package/dist/esm/{ChatInput.js → chat/chat-input.js} +4 -4
  48. package/dist/esm/chat/chat-thread.d.ts +12 -0
  49. package/dist/esm/{ChatThread.js → chat/chat-thread.js} +70 -23
  50. package/dist/esm/{ChatTypingIndicator.js → chat/chat-typing-indicator.js} +1 -1
  51. package/dist/{cjs → esm/chat}/conversation-descriptor.d.ts +7 -1
  52. package/dist/esm/{conversation-descriptor.js → chat/conversation-descriptor.js} +41 -7
  53. package/dist/esm/chat/dataset-chat-thread.d.ts +13 -0
  54. package/dist/esm/chat/dataset-chat-thread.js +1815 -0
  55. package/dist/esm/{FileUploader.js → chat/file-uploader.js} +1 -1
  56. package/dist/esm/{multi-thread-view.js → chat/multi-thread-view.js} +8 -3
  57. package/dist/esm/chat/new-chat-thread.d.ts +17 -0
  58. package/dist/esm/{Chat.js → chat/new-chat-thread.js} +40 -165
  59. package/dist/esm/{UploadPill.js → chat/upload-pill.js} +2 -2
  60. package/dist/esm/file-preview/file-preview.d.ts +34 -0
  61. package/dist/esm/file-preview/file-preview.js +316 -0
  62. package/dist/esm/forms/email-address.d.ts +10 -0
  63. package/dist/esm/forms/email-address.js +85 -0
  64. package/dist/esm/forms/form.d.ts +27 -0
  65. package/dist/esm/forms/form.js +193 -0
  66. package/dist/esm/forms/multi-select-autocomplete.d.ts +35 -0
  67. package/dist/esm/forms/multi-select-autocomplete.js +274 -0
  68. package/dist/esm/forms/select-users-dialog.d.ts +20 -0
  69. package/dist/esm/forms/select-users-dialog.js +132 -0
  70. package/dist/esm/forms/select-users.d.ts +16 -0
  71. package/dist/esm/forms/select-users.js +97 -0
  72. package/dist/esm/index.d.ts +19 -11
  73. package/dist/esm/index.js +19 -11
  74. package/dist/esm/meetings/audio-visualization.d.ts +7 -0
  75. package/dist/esm/meetings/audio-visualization.js +54 -0
  76. package/dist/esm/meetings/controls.d.ts +19 -0
  77. package/dist/esm/meetings/controls.js +294 -0
  78. package/dist/esm/meetings/meeting-scope.d.ts +83 -0
  79. package/dist/esm/meetings/meeting-scope.js +294 -0
  80. package/dist/esm/meetings/meetings.d.ts +5 -0
  81. package/dist/esm/meetings/meetings.js +5 -0
  82. package/dist/esm/meetings/participants.d.ts +13 -0
  83. package/dist/esm/meetings/participants.js +137 -0
  84. package/dist/esm/meetings/wake-lock.d.ts +4 -0
  85. package/dist/esm/meetings/wake-lock.js +35 -0
  86. package/dist/index.css +2 -2
  87. package/package.json +7 -4
  88. package/dist/cjs/Chat.d.ts +0 -15
  89. package/dist/cjs/ChatThread.d.ts +0 -21
  90. package/dist/esm/Chat.d.ts +0 -15
  91. package/dist/esm/ChatThread.d.ts +0 -21
  92. /package/dist/cjs/{ChatBotView.d.ts → chat/chat-bot-view.d.ts} +0 -0
  93. /package/dist/cjs/{ChatInput.d.ts → chat/chat-input.d.ts} +0 -0
  94. /package/dist/cjs/{chat-message.d.ts → chat/chat-message.d.ts} +0 -0
  95. /package/dist/cjs/{chat-message.js → chat/chat-message.js} +0 -0
  96. /package/dist/cjs/{ChatTypingIndicator.d.ts → chat/chat-typing-indicator.d.ts} +0 -0
  97. /package/dist/cjs/{file-attachment.d.ts → chat/file-attachment.d.ts} +0 -0
  98. /package/dist/cjs/{file-attachment.js → chat/file-attachment.js} +0 -0
  99. /package/dist/cjs/{FileUploader.d.ts → chat/file-uploader.d.ts} +0 -0
  100. /package/dist/cjs/{multi-thread-view.d.ts → chat/multi-thread-view.d.ts} +0 -0
  101. /package/dist/cjs/{UploadPill.d.ts → chat/upload-pill.d.ts} +0 -0
  102. /package/dist/esm/{ChatBotView.d.ts → chat/chat-bot-view.d.ts} +0 -0
  103. /package/dist/esm/{ChatInput.d.ts → chat/chat-input.d.ts} +0 -0
  104. /package/dist/esm/{chat-message.d.ts → chat/chat-message.d.ts} +0 -0
  105. /package/dist/esm/{chat-message.js → chat/chat-message.js} +0 -0
  106. /package/dist/esm/{ChatTypingIndicator.d.ts → chat/chat-typing-indicator.d.ts} +0 -0
  107. /package/dist/esm/{file-attachment.d.ts → chat/file-attachment.d.ts} +0 -0
  108. /package/dist/esm/{file-attachment.js → chat/file-attachment.js} +0 -0
  109. /package/dist/esm/{FileUploader.d.ts → chat/file-uploader.d.ts} +0 -0
  110. /package/dist/esm/{multi-thread-view.d.ts → chat/multi-thread-view.d.ts} +0 -0
  111. /package/dist/esm/{UploadPill.d.ts → chat/upload-pill.d.ts} +0 -0
@@ -0,0 +1,35 @@
1
+ import type { ReactElement } from "react";
2
+ export type AsyncSearch = (query: string) => Promise<string[]> | string[];
3
+ export declare class MultiSelectController {
4
+ private listeners;
5
+ private _value;
6
+ constructor(initialValue?: string[]);
7
+ get value(): string[];
8
+ set value(nextValue: string[]);
9
+ add(item: string): Promise<boolean>;
10
+ canAddItem(_item: string): boolean | Promise<boolean>;
11
+ remove(item: string): void;
12
+ removeLast(): void;
13
+ clear(): void;
14
+ subscribe(listener: (value: string[]) => void): () => void;
15
+ dispose(): void;
16
+ private notify;
17
+ }
18
+ export declare function MultiSelectAutocomplete({ search, onChanged, controller, placeholder, debounceDuration, minimumSearchLength, initialValue, value, autoFocus, className, inputClassName, onTextChanged, }: {
19
+ search: AsyncSearch;
20
+ onChanged?: (value: string[]) => void;
21
+ controller?: MultiSelectController;
22
+ placeholder?: string;
23
+ debounceDuration?: number;
24
+ minimumSearchLength?: number;
25
+ initialValue?: string[];
26
+ value?: string[];
27
+ autoFocus?: boolean;
28
+ className?: string;
29
+ inputClassName?: string;
30
+ onTextChanged?: (text: string, context: {
31
+ add: (item: string) => Promise<void>;
32
+ setText: (text: string) => void;
33
+ controller: MultiSelectController;
34
+ }) => void;
35
+ }): ReactElement;
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var multi_select_autocomplete_exports = {};
20
+ __export(multi_select_autocomplete_exports, {
21
+ MultiSelectAutocomplete: () => MultiSelectAutocomplete,
22
+ MultiSelectController: () => MultiSelectController
23
+ });
24
+ module.exports = __toCommonJS(multi_select_autocomplete_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_react = require("react");
27
+ var import_lucide_react = require("lucide-react");
28
+ var import_utils = require("../lib/utils");
29
+ class MultiSelectController {
30
+ listeners = /* @__PURE__ */ new Set();
31
+ _value;
32
+ constructor(initialValue = []) {
33
+ this._value = [...initialValue];
34
+ }
35
+ get value() {
36
+ return [...this._value];
37
+ }
38
+ set value(nextValue) {
39
+ this._value = [...nextValue];
40
+ this.notify();
41
+ }
42
+ async add(item) {
43
+ if (!await this.canAddItem(item)) {
44
+ return false;
45
+ }
46
+ this.value = [...this._value, item];
47
+ return true;
48
+ }
49
+ canAddItem(_item) {
50
+ return true;
51
+ }
52
+ remove(item) {
53
+ this.value = this._value.filter((current) => current !== item);
54
+ }
55
+ removeLast() {
56
+ if (this._value.length > 0) {
57
+ this.value = this._value.slice(0, -1);
58
+ }
59
+ }
60
+ clear() {
61
+ this.value = [];
62
+ }
63
+ subscribe(listener) {
64
+ this.listeners.add(listener);
65
+ return () => {
66
+ this.listeners.delete(listener);
67
+ };
68
+ }
69
+ dispose() {
70
+ this.listeners.clear();
71
+ }
72
+ notify() {
73
+ const value = this.value;
74
+ for (const listener of this.listeners) {
75
+ listener(value);
76
+ }
77
+ }
78
+ }
79
+ function containsSelected(selected, value) {
80
+ const normalized = value.toLowerCase();
81
+ return selected.some((item) => item.toLowerCase() === normalized);
82
+ }
83
+ function MultiSelectAutocomplete({
84
+ search,
85
+ onChanged,
86
+ controller,
87
+ placeholder = "Type a value",
88
+ debounceDuration = 300,
89
+ minimumSearchLength = 2,
90
+ initialValue = [],
91
+ value,
92
+ autoFocus = false,
93
+ className,
94
+ inputClassName,
95
+ onTextChanged
96
+ }) {
97
+ const generatedController = (0, import_react.useMemo)(() => controller ?? new MultiSelectController(initialValue), [controller]);
98
+ const [selected, setSelected] = (0, import_react.useState)(() => value ?? generatedController.value);
99
+ const [text, setText] = (0, import_react.useState)("");
100
+ const [options, setOptions] = (0, import_react.useState)([]);
101
+ const [selectedOption, setSelectedOption] = (0, import_react.useState)(0);
102
+ const [open, setOpen] = (0, import_react.useState)(false);
103
+ const sequence = (0, import_react.useRef)(0);
104
+ const inputRef = (0, import_react.useRef)(null);
105
+ const listboxId = (0, import_react.useId)();
106
+ (0, import_react.useEffect)(() => {
107
+ if (value != null) {
108
+ setSelected(value);
109
+ generatedController.value = value;
110
+ }
111
+ }, [generatedController, value]);
112
+ (0, import_react.useEffect)(() => {
113
+ return generatedController.subscribe((nextValue) => {
114
+ setSelected(nextValue);
115
+ onChanged?.(nextValue);
116
+ });
117
+ }, [generatedController, onChanged]);
118
+ (0, import_react.useEffect)(() => {
119
+ if (controller == null) {
120
+ return () => {
121
+ generatedController.dispose();
122
+ };
123
+ }
124
+ return void 0;
125
+ }, [controller, generatedController]);
126
+ (0, import_react.useEffect)(() => {
127
+ const query = text.trim();
128
+ if (query.length < minimumSearchLength) {
129
+ setOpen(false);
130
+ setOptions([]);
131
+ return void 0;
132
+ }
133
+ const currentSequence = sequence.current + 1;
134
+ sequence.current = currentSequence;
135
+ const timeout = window.setTimeout(() => {
136
+ void Promise.resolve(search(query)).then((results) => {
137
+ if (sequence.current !== currentSequence) {
138
+ return;
139
+ }
140
+ const filtered = results.filter((item) => !containsSelected(generatedController.value, item));
141
+ setOptions(filtered);
142
+ setSelectedOption(0);
143
+ setOpen(filtered.length > 0);
144
+ });
145
+ }, debounceDuration);
146
+ return () => {
147
+ window.clearTimeout(timeout);
148
+ };
149
+ }, [debounceDuration, generatedController, minimumSearchLength, search, text]);
150
+ const add = (0, import_react.useCallback)(async (item) => {
151
+ const trimmed = item.trim();
152
+ if (trimmed === "") {
153
+ return;
154
+ }
155
+ const added = await generatedController.add(trimmed);
156
+ if (!added) {
157
+ return;
158
+ }
159
+ setText("");
160
+ setOpen(false);
161
+ setOptions([]);
162
+ inputRef.current?.focus();
163
+ }, [generatedController]);
164
+ const remove = (0, import_react.useCallback)((item) => {
165
+ generatedController.remove(item);
166
+ inputRef.current?.focus();
167
+ }, [generatedController]);
168
+ const handleTextChange = (0, import_react.useCallback)((nextText) => {
169
+ setText(nextText);
170
+ onTextChanged?.(nextText, {
171
+ add,
172
+ setText,
173
+ controller: generatedController
174
+ });
175
+ }, [add, generatedController, onTextChanged]);
176
+ const handleKeyDown = (0, import_react.useCallback)((event) => {
177
+ if (event.key === "Backspace" && text === "") {
178
+ generatedController.removeLast();
179
+ return;
180
+ }
181
+ if (event.key === "Escape") {
182
+ setOpen(false);
183
+ return;
184
+ }
185
+ if (event.key === "ArrowDown") {
186
+ event.preventDefault();
187
+ if (options.length > 0) {
188
+ setOpen(true);
189
+ setSelectedOption((index) => Math.min(index + 1, options.length - 1));
190
+ }
191
+ return;
192
+ }
193
+ if (event.key === "ArrowUp") {
194
+ event.preventDefault();
195
+ if (options.length > 0) {
196
+ setSelectedOption((index) => Math.max(index - 1, 0));
197
+ }
198
+ return;
199
+ }
200
+ if (event.key === "Enter") {
201
+ event.preventDefault();
202
+ const option = open ? options[selectedOption] : void 0;
203
+ void add(option ?? text);
204
+ }
205
+ }, [add, generatedController, open, options, selectedOption, text]);
206
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
208
+ "div",
209
+ {
210
+ className: (0, import_utils.cn)(
211
+ "border-input focus-within:border-ring focus-within:ring-ring/50 flex min-h-9 w-full flex-wrap items-center gap-2 rounded-md border bg-transparent px-2 py-1.5 text-sm shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]",
212
+ className
213
+ ),
214
+ onClick: () => inputRef.current?.focus(),
215
+ children: [
216
+ selected.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
217
+ "span",
218
+ {
219
+ className: "inline-flex max-w-full items-center gap-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground",
220
+ children: [
221
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: item }),
222
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
223
+ "button",
224
+ {
225
+ type: "button",
226
+ className: "rounded-sm opacity-80 transition-opacity hover:opacity-100 focus:outline-none focus:ring-1 focus:ring-primary-foreground",
227
+ onClick: (event) => {
228
+ event.stopPropagation();
229
+ remove(item);
230
+ },
231
+ "aria-label": `Remove ${item}`,
232
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "h-3.5 w-3.5" })
233
+ }
234
+ )
235
+ ]
236
+ },
237
+ item
238
+ )),
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
240
+ "input",
241
+ {
242
+ ref: inputRef,
243
+ value: text,
244
+ autoFocus,
245
+ onChange: (event) => handleTextChange(event.currentTarget.value),
246
+ onKeyDown: handleKeyDown,
247
+ onBlur: () => {
248
+ window.setTimeout(() => setOpen(false), 120);
249
+ },
250
+ placeholder: selected.length === 0 ? placeholder : void 0,
251
+ className: (0, import_utils.cn)(
252
+ "min-w-24 flex-1 bg-transparent px-1 py-0.5 outline-none placeholder:text-muted-foreground",
253
+ inputClassName
254
+ ),
255
+ role: "combobox",
256
+ "aria-expanded": open,
257
+ "aria-controls": open ? listboxId : void 0,
258
+ "aria-autocomplete": "list"
259
+ }
260
+ )
261
+ ]
262
+ }
263
+ ),
264
+ open ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
265
+ "div",
266
+ {
267
+ id: listboxId,
268
+ role: "listbox",
269
+ className: "absolute left-0 top-full z-50 mt-2 max-h-80 w-full min-w-64 overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
270
+ children: options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
271
+ "button",
272
+ {
273
+ type: "button",
274
+ role: "option",
275
+ "aria-selected": index === selectedOption,
276
+ className: (0, import_utils.cn)(
277
+ "flex h-9 w-full items-center rounded-sm px-2 text-left text-sm outline-none transition-colors",
278
+ index === selectedOption ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground"
279
+ ),
280
+ onMouseEnter: () => setSelectedOption(index),
281
+ onMouseDown: (event) => {
282
+ event.preventDefault();
283
+ },
284
+ onClick: () => {
285
+ void add(option);
286
+ },
287
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: option })
288
+ },
289
+ option
290
+ ))
291
+ }
292
+ ) : null
293
+ ] });
294
+ }
@@ -0,0 +1,20 @@
1
+ import type { ReactElement } from "react";
2
+ export declare function showSelectUsersDialog({ projectEmails, initialValue, title, description, confirmLabel, cancelLabel, }: {
3
+ projectEmails: string[];
4
+ initialValue?: string[];
5
+ title?: string;
6
+ description?: string;
7
+ confirmLabel?: string;
8
+ cancelLabel?: string;
9
+ }): Promise<string[] | null>;
10
+ export declare function SelectUsersDialog({ projectEmails, initialValue, title, description, confirmLabel, cancelLabel, onSubmit, onCancel, onCleanup, }: {
11
+ projectEmails: string[];
12
+ initialValue?: string[];
13
+ title?: string;
14
+ description?: string;
15
+ confirmLabel?: string;
16
+ cancelLabel?: string;
17
+ onSubmit?: (value: string[]) => void;
18
+ onCancel?: () => void;
19
+ onCleanup?: () => void;
20
+ }): ReactElement;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var select_users_dialog_exports = {};
20
+ __export(select_users_dialog_exports, {
21
+ SelectUsersDialog: () => SelectUsersDialog,
22
+ showSelectUsersDialog: () => showSelectUsersDialog
23
+ });
24
+ module.exports = __toCommonJS(select_users_dialog_exports);
25
+ var import_jsx_runtime = require("react/jsx-runtime");
26
+ var import_react = require("react");
27
+ var import_client = require("react-dom/client");
28
+ var import_react_form = require("@tanstack/react-form");
29
+ var import_dialog = require("../components/ui/dialog");
30
+ var import_button = require("../components/ui/button");
31
+ var import_select_users = require("./select-users");
32
+ function showSelectUsersDialog({
33
+ projectEmails,
34
+ initialValue = [],
35
+ title = "Select users",
36
+ description = "Choose one or more project users.",
37
+ confirmLabel = "Apply",
38
+ cancelLabel = "Cancel"
39
+ }) {
40
+ return new Promise((resolve) => {
41
+ const container = document.createElement("div");
42
+ document.body.appendChild(container);
43
+ const root = (0, import_client.createRoot)(container);
44
+ const cleanup = () => {
45
+ root.unmount();
46
+ container.remove();
47
+ };
48
+ root.render(
49
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
50
+ SelectUsersDialog,
51
+ {
52
+ projectEmails,
53
+ initialValue,
54
+ title,
55
+ description,
56
+ confirmLabel,
57
+ cancelLabel,
58
+ onSubmit: resolve,
59
+ onCancel: () => resolve(null),
60
+ onCleanup: cleanup
61
+ }
62
+ )
63
+ );
64
+ });
65
+ }
66
+ function SelectUsersDialog({
67
+ projectEmails,
68
+ initialValue = [],
69
+ title = "Select users",
70
+ description = "Choose one or more project users.",
71
+ confirmLabel = "Apply",
72
+ cancelLabel = "Cancel",
73
+ onSubmit,
74
+ onCancel,
75
+ onCleanup
76
+ }) {
77
+ const [open, setOpen] = (0, import_react.useState)(true);
78
+ const form = (0, import_react_form.useForm)({
79
+ defaultValues: {
80
+ users: initialValue
81
+ },
82
+ onSubmit: ({ value }) => {
83
+ onSubmit?.(value.users);
84
+ setOpen(false);
85
+ }
86
+ });
87
+ const close = (0, import_react.useCallback)(() => {
88
+ onCancel?.();
89
+ setOpen(false);
90
+ }, [onCancel]);
91
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
92
+ import_dialog.Dialog,
93
+ {
94
+ open,
95
+ onOpenChange: (nextOpen) => {
96
+ if (!nextOpen) {
97
+ close();
98
+ }
99
+ },
100
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
101
+ import_dialog.DialogContent,
102
+ {
103
+ className: "max-w-[min(92vw,560px)]",
104
+ onAnimationEnd: () => {
105
+ if (!open) {
106
+ onCleanup?.();
107
+ }
108
+ },
109
+ children: [
110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogHeader, { children: [
111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogTitle, { children: title }),
112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogDescription, { children: description })
113
+ ] }),
114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
115
+ "form",
116
+ {
117
+ className: "grid gap-4",
118
+ onSubmit: (event) => {
119
+ event.preventDefault();
120
+ event.stopPropagation();
121
+ void form.handleSubmit();
122
+ },
123
+ children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(form.Field, { name: "users", children: (field) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
125
+ import_select_users.SelectUsers,
126
+ {
127
+ autoFocus: true,
128
+ projectEmails,
129
+ value: field.state.value,
130
+ onChanged: (value) => field.handleChange(value)
131
+ }
132
+ ) }),
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogFooter, { children: [
134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "button", variant: "outline", onClick: close, children: cancelLabel }),
135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "submit", children: confirmLabel })
136
+ ] })
137
+ ]
138
+ }
139
+ )
140
+ ]
141
+ }
142
+ )
143
+ }
144
+ );
145
+ }
@@ -0,0 +1,16 @@
1
+ import type { ReactElement } from "react";
2
+ import { MultiSelectController } from "./multi-select-autocomplete";
3
+ export declare class SelectUsersController extends MultiSelectController {
4
+ static readonly emailRegex: RegExp;
5
+ canAddItem(item: string): boolean;
6
+ }
7
+ export declare function SelectUsers({ projectEmails, onChanged, controller, autoFocus, initialValue, value, className, }: {
8
+ projectEmails: string[];
9
+ onChanged?: (value: string[]) => void;
10
+ controller?: SelectUsersController;
11
+ autoFocus?: boolean;
12
+ initialValue?: string[];
13
+ value?: string[];
14
+ className?: string;
15
+ }): ReactElement;
16
+ export declare function buildSelectedUsersResult(selected: readonly string[], pendingEmail: string): string[];
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var select_users_exports = {};
20
+ __export(select_users_exports, {
21
+ SelectUsers: () => SelectUsers,
22
+ SelectUsersController: () => SelectUsersController,
23
+ buildSelectedUsersResult: () => buildSelectedUsersResult
24
+ });
25
+ module.exports = __toCommonJS(select_users_exports);
26
+ var import_jsx_runtime = require("react/jsx-runtime");
27
+ var import_react = require("react");
28
+ var import_email_address = require("./email-address");
29
+ var import_multi_select_autocomplete = require("./multi-select-autocomplete");
30
+ class SelectUsersController extends import_multi_select_autocomplete.MultiSelectController {
31
+ static emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/u;
32
+ canAddItem(item) {
33
+ return SelectUsersController.emailRegex.test(item);
34
+ }
35
+ }
36
+ function selectedIncludes(selected, email) {
37
+ const normalized = email.toLowerCase();
38
+ return selected.some((item) => item.toLowerCase() === normalized);
39
+ }
40
+ function SelectUsers({
41
+ projectEmails,
42
+ onChanged,
43
+ controller,
44
+ autoFocus = false,
45
+ initialValue = [],
46
+ value,
47
+ className
48
+ }) {
49
+ const effectiveController = (0, import_react.useMemo)(
50
+ () => controller ?? new SelectUsersController(initialValue),
51
+ [controller]
52
+ );
53
+ (0, import_react.useEffect)(() => {
54
+ if (controller != null) {
55
+ return void 0;
56
+ }
57
+ return () => {
58
+ effectiveController.dispose();
59
+ };
60
+ }, [controller, effectiveController]);
61
+ const search = (0, import_react.useCallback)((query) => {
62
+ if (query.trim() === "") {
63
+ return projectEmails;
64
+ }
65
+ const lower = query.toLowerCase();
66
+ return projectEmails.filter((email) => email.toLowerCase().includes(lower));
67
+ }, [projectEmails]);
68
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
69
+ import_multi_select_autocomplete.MultiSelectAutocomplete,
70
+ {
71
+ search,
72
+ controller: effectiveController,
73
+ onChanged,
74
+ initialValue,
75
+ value,
76
+ autoFocus,
77
+ placeholder: "Type an email",
78
+ minimumSearchLength: 1,
79
+ className,
80
+ onTextChanged: (text, { add, setText }) => {
81
+ if (text.trim() === "") {
82
+ return;
83
+ }
84
+ const parsed = (0, import_email_address.parseEmailList)(text);
85
+ if (parsed.length === 0) {
86
+ return;
87
+ }
88
+ if (parsed.length === 1) {
89
+ if (text.endsWith(" ") || text.endsWith(",")) {
90
+ const email = parsed[0]?.sanitizedAddress.trim() ?? "";
91
+ if (SelectUsersController.emailRegex.test(email)) {
92
+ void add(email);
93
+ setText("");
94
+ }
95
+ }
96
+ return;
97
+ }
98
+ for (const address of parsed.slice(0, -1)) {
99
+ const email = address.sanitizedAddress.trim();
100
+ if (SelectUsersController.emailRegex.test(email)) {
101
+ void add(email);
102
+ }
103
+ }
104
+ const remainder = parsed[parsed.length - 1]?.sanitizedAddress.trim() ?? "";
105
+ setText(remainder);
106
+ }
107
+ }
108
+ );
109
+ }
110
+ function buildSelectedUsersResult(selected, pendingEmail) {
111
+ const result = [...selected];
112
+ const trimmed = pendingEmail.trim();
113
+ if (SelectUsersController.emailRegex.test(trimmed) && !selectedIncludes(result, trimmed)) {
114
+ result.push(trimmed);
115
+ }
116
+ return result;
117
+ }
@@ -1,11 +1,19 @@
1
- export * from './Chat';
2
- export * from './ChatBotView';
3
- export * from './ChatInput';
4
- export * from './ChatThread';
5
- export * from './ChatTypingIndicator';
6
- export * from './FileUploader';
7
- export * from './chat-message';
8
- export * from './conversation-descriptor';
9
- export * from './file-attachment';
10
- export * from './multi-thread-view';
11
- export * from './chat-hooks';
1
+ export * from './chat/chat-bot-view';
2
+ export * from './chat/chat-hooks';
3
+ export * from './chat/chat-input';
4
+ export * from './chat/chat-message';
5
+ export * from './chat/chat-thread';
6
+ export * from './chat/chat-typing-indicator';
7
+ export * from './chat/conversation-descriptor';
8
+ export * from './chat/dataset-chat-thread';
9
+ export * from './chat/file-attachment';
10
+ export * from './chat/file-uploader';
11
+ export * from './chat/multi-thread-view';
12
+ export * from './chat/new-chat-thread';
13
+ export * from './file-preview/file-preview';
14
+ export * from './forms/email-address';
15
+ export * from './forms/form';
16
+ export * from './forms/multi-select-autocomplete';
17
+ export * from './forms/select-users';
18
+ export * from './forms/select-users-dialog';
19
+ export * from './meetings/meetings';