@reforma/components 0.1.2 → 0.1.4

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 (46) hide show
  1. package/dist/Composer/Composer.module.css +1 -0
  2. package/dist/Composer/Composer.module.css.js +26 -0
  3. package/dist/Composer/Composer.module.css.js.map +1 -0
  4. package/dist/Composer/RichField.d.ts +3 -0
  5. package/dist/Composer/RichField.d.ts.map +1 -0
  6. package/dist/Composer/RichField.js +44 -0
  7. package/dist/Composer/RichField.js.map +1 -0
  8. package/dist/Composer/context.d.ts +44 -0
  9. package/dist/Composer/context.d.ts.map +1 -0
  10. package/dist/Composer/context.js +205 -0
  11. package/dist/Composer/context.js.map +1 -0
  12. package/dist/Composer/index.d.ts +5 -0
  13. package/dist/Composer/index.d.ts.map +1 -0
  14. package/dist/Composer/index.js +18 -0
  15. package/dist/{CreateComposer → Composer}/index.js.map +1 -1
  16. package/dist/Composer/parts.d.ts +22 -0
  17. package/dist/Composer/parts.d.ts.map +1 -0
  18. package/dist/Composer/parts.js +231 -0
  19. package/dist/Composer/parts.js.map +1 -0
  20. package/dist/{CreateComposer → Composer}/types.d.ts +6 -6
  21. package/dist/Composer/types.d.ts.map +1 -0
  22. package/dist/Modal/Modal.js +2 -2
  23. package/dist/Modal/Modal.js.map +1 -1
  24. package/dist/chat/Message/turn/MessageTurnStore.js +23 -23
  25. package/dist/chat/Message/turn/MessageTurnStore.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +317 -304
  29. package/dist/index.js.map +1 -1
  30. package/dist/modals/ConfirmModal.d.ts +3 -1
  31. package/dist/modals/ConfirmModal.d.ts.map +1 -1
  32. package/dist/modals/ConfirmModal.js +61 -55
  33. package/dist/modals/ConfirmModal.js.map +1 -1
  34. package/dist/node_modules/react-aria/dist/private/interactions/useFocusable.js.map +1 -1
  35. package/package.json +1 -1
  36. package/dist/CreateComposer/CreateComposer.d.ts +0 -26
  37. package/dist/CreateComposer/CreateComposer.d.ts.map +0 -1
  38. package/dist/CreateComposer/CreateComposer.js +0 -338
  39. package/dist/CreateComposer/CreateComposer.js.map +0 -1
  40. package/dist/CreateComposer/CreateComposer.module.css +0 -1
  41. package/dist/CreateComposer/CreateComposer.module.css.js +0 -24
  42. package/dist/CreateComposer/CreateComposer.module.css.js.map +0 -1
  43. package/dist/CreateComposer/index.d.ts +0 -3
  44. package/dist/CreateComposer/index.d.ts.map +0 -1
  45. package/dist/CreateComposer/index.js +0 -5
  46. package/dist/CreateComposer/types.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ @layer components{@property --border-angle{syntax: "<angle>"; inherits: false; initial-value: 0deg;}@keyframes Composer_create-composer-border-spin_e2I1Qy{to{--border-angle: 360deg}}.Composer_root_nvLX5v{display:flex;flex-direction:column;gap:var(--spacing-xl);width:100%}.Composer_shell_wSLYtf{display:flex;position:relative;flex-direction:column;z-index:1;border-radius:calc(var(--radius-xl) * var(--squircle-radius-factor));padding:var(--spacing-6);width:100%;font-weight:400;font-size:var(--text-md);line-height:var(--leading-md);font-family:Onest,sans-serif;letter-spacing:0;corner-shape:superellipse(var(--squircle-value));--composer-border-coral: rgba(250, 136, 84, .16);--composer-border-blue: rgba(91, 141, 239, .28);--composer-border-pink: rgba(255, 161, 231, .26);transition:box-shadow var(--transition-duration) var(--ease-in-out);container-type:inline-size;background-color:var(--color-chat-composer);overflow:hidden;line-height:var(--spacing-20)}.dark .Composer_shell_wSLYtf{--composer-border-coral: rgba(250, 136, 84, .15);--composer-border-blue: rgba(91, 141, 239, .2);--composer-border-pink: rgba(255, 161, 231, .18)}.Composer_shell_wSLYtf:focus-within{box-shadow:0 0 var(--spacing-20) var(--spacing-1) var(--color-chat-shadow)}.Composer_shell_wSLYtf:before{position:absolute;inset:0;border-radius:inherit;content:"";corner-shape:inherit;animation:Composer_create-composer-border-spin_e2I1Qy 6s linear infinite;background-image:conic-gradient(from var(--border-angle),var(--composer-border-coral),var(--composer-border-blue) 50%,var(--composer-border-pink),var(--composer-border-coral));padding:2px;pointer-events:none;-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}.Composer_attachments_yMqV5C{display:flex;flex-wrap:wrap;gap:var(--spacing-4);padding:var(--spacing-sm) var(--spacing-sm) var(--spacing-xxs)}.Composer_main_cG4JpA{display:flex;position:relative;flex:1;flex-direction:column;z-index:0;cursor:text;padding:var(--spacing-sm);min-width:0;min-height:0}.Composer_main_cG4JpA[data-expanded] .Composer_textarea_B33BWC{margin-bottom:var(--spacing-sm);padding-bottom:var(--spacing-30);padding-inline:0}.Composer_main_cG4JpA:not([data-expanded]){display:flex;align-items:center;min-height:var(--spacing-30)}.Composer_main_cG4JpA:not([data-expanded]) .Composer_textareaWrap_IFAg1U{display:flex;align-items:center;min-height:var(--spacing-30)}.Composer_main_cG4JpA:not([data-expanded]) .Composer_textarea_B33BWC{display:flex;flex:1;align-items:center;padding-right:var(--spacing-40);padding-left:var(--spacing-36);min-width:0;min-height:var(--spacing-30)!important}.Composer_main_cG4JpA:not([data-expanded]) .Composer_textarea_B33BWC [contenteditable=true]{width:100%;min-height:0!important;overflow:hidden!important}.Composer_main_cG4JpA[data-min-rows] .Composer_textarea_B33BWC [contenteditable=true]{width:100%}.Composer_main_cG4JpA:not([data-expanded]) .Composer_addButton_fa1dRf,.Composer_main_cG4JpA:not([data-expanded]) .Composer_sendButton_NrBb6Q,.Composer_main_cG4JpA:not([data-expanded]) .Composer_toolbarEnd_XqHb9b{top:0;bottom:0;margin-block:auto}.Composer_textareaWrap_IFAg1U{position:relative;flex:1;z-index:1;min-width:0}.Composer_textarea_B33BWC{position:relative;border:0;width:100%;min-height:var(--spacing-30)!important}.Composer_plainField_nIzUoy{display:block;outline:none;background:transparent;padding:0;max-height:280px;overflow:auto;resize:none;color:inherit;font:inherit;line-height:inherit}.Composer_addButton_fa1dRf,.Composer_toolbarEnd_XqHb9b,.Composer_sendButton_NrBb6Q{position:absolute;bottom:var(--spacing-xs);z-index:2}.Composer_addButton_fa1dRf{display:flex;left:var(--spacing-xs);align-items:center;gap:var(--spacing-xs)}.Composer_toolbarEnd_XqHb9b{display:flex;right:calc(var(--spacing-xs) + var(--spacing-30) + var(--spacing-xs));align-items:center;gap:0;max-width:calc(100% - var(--spacing-80))}.Composer_sendButton_NrBb6Q{right:var(--spacing-xs)}}
@@ -0,0 +1,26 @@
1
+ const t = "Composer_root_nvLX5v", o = "Composer_shell_wSLYtf", e = "Composer_attachments_yMqV5C", a = "Composer_main_cG4JpA", n = "Composer_textarea_B33BWC", s = "Composer_textareaWrap_IFAg1U", r = "Composer_addButton_fa1dRf", _ = "Composer_sendButton_NrBb6Q", p = "Composer_toolbarEnd_XqHb9b", d = "Composer_plainField_nIzUoy", l = {
2
+ root: t,
3
+ shell: o,
4
+ attachments: e,
5
+ main: a,
6
+ textarea: n,
7
+ textareaWrap: s,
8
+ addButton: r,
9
+ sendButton: _,
10
+ toolbarEnd: p,
11
+ plainField: d
12
+ };
13
+ export {
14
+ r as addButton,
15
+ e as attachments,
16
+ l as default,
17
+ a as main,
18
+ d as plainField,
19
+ t as root,
20
+ _ as sendButton,
21
+ o as shell,
22
+ n as textarea,
23
+ s as textareaWrap,
24
+ p as toolbarEnd
25
+ };
26
+ //# sourceMappingURL=Composer.module.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Composer.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
@@ -0,0 +1,3 @@
1
+ /** TipTap prompt field. Import this only when the plain textarea is not enough. */
2
+ export declare function ComposerRichField(): import("react").JSX.Element;
3
+ //# sourceMappingURL=RichField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichField.d.ts","sourceRoot":"","sources":["../../src/Composer/RichField.tsx"],"names":[],"mappings":"AAWA,mFAAmF;AACnF,wBAAgB,iBAAiB,gCAoChC"}
@@ -0,0 +1,44 @@
1
+ import { useMemo as x } from "react";
2
+ import { plainTextToDoc as d, docToPlainText as h } from "../RichInput/composerDoc.js";
3
+ import { RichInput as T } from "../RichInput/RichInput.js";
4
+ import r from "./Composer.module.css.js";
5
+ import { useComposer as F } from "./context.js";
6
+ import { jsx as m } from "react/jsx-runtime";
7
+ function H() {
8
+ const {
9
+ value: o,
10
+ setPrompt: a,
11
+ submit: i,
12
+ placeholder: t,
13
+ autoFocus: s,
14
+ submitOnEnter: p,
15
+ minHeight: n,
16
+ focusRef: l,
17
+ addFiles: c,
18
+ pasteTextAsFile: u
19
+ } = F(), f = x(() => d(o.prompt), [o.prompt]);
20
+ return /* @__PURE__ */ m("div", {
21
+ className: r.textareaWrap,
22
+ children: /* @__PURE__ */ m(T, {
23
+ ref: (e) => {
24
+ l.current = e;
25
+ },
26
+ value: f,
27
+ onChange: (e) => a(h(e)),
28
+ autoFocus: s,
29
+ minHeight: n,
30
+ maxHeight: 280,
31
+ placeholder: t,
32
+ className: r.textarea,
33
+ "aria-label": t,
34
+ submitOnEnter: p,
35
+ onSubmit: () => i(),
36
+ onPasteFiles: (e) => c(e),
37
+ onPasteText: u
38
+ })
39
+ });
40
+ }
41
+ export {
42
+ H as ComposerRichField
43
+ };
44
+ //# sourceMappingURL=RichField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichField.js","sources":["../../src/Composer/RichField.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo } from 'react';\n\nimport { docToPlainText, plainTextToDoc } from '../RichInput';\nimport { RichInput } from '../RichInput/RichInput';\nimport styles from './Composer.module.css';\nimport { useComposer } from './context';\n\nimport type { RichInputHandle } from '../RichInput/types';\n\n/** TipTap prompt field. Import this only when the plain textarea is not enough. */\nexport function ComposerRichField() {\n const {\n value,\n setPrompt,\n submit,\n placeholder,\n autoFocus,\n submitOnEnter,\n minHeight,\n focusRef,\n addFiles,\n pasteTextAsFile,\n } = useComposer();\n const doc = useMemo(() => plainTextToDoc(value.prompt), [value.prompt]);\n\n return (\n <div className={ styles.textareaWrap }>\n <RichInput\n ref={ (node: RichInputHandle | null) => {\n focusRef.current = node;\n } }\n value={ doc }\n onChange={ (next) => setPrompt(docToPlainText(next)) }\n autoFocus={ autoFocus }\n minHeight={ minHeight }\n maxHeight={ 280 }\n placeholder={ placeholder }\n className={ styles.textarea }\n aria-label={ placeholder }\n submitOnEnter={ submitOnEnter }\n onSubmit={ () => submit() }\n onPasteFiles={ files => addFiles(files) }\n onPasteText={ pasteTextAsFile }\n />\n </div>\n );\n}\n"],"names":["ComposerRichField","value","setPrompt","submit","placeholder","autoFocus","submitOnEnter","minHeight","focusRef","addFiles","pasteTextAsFile","useComposer","doc","useMemo","plainTextToDoc","styles","RichInput","node","next","docToPlainText","files"],"mappings":";;;;;;AASO,SAASA,IAAoB;AAClC,QAAM;AAAA,IACJ,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAAC;AAAA,IACA,eAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,iBAAAC;AAAA,EAAA,IACEC,EAAA,GACEC,IAAMC,EAAQ,MAAMC,EAAeb,EAAM,MAAM,GAAG,CAACA,EAAM,MAAM,CAAC;AACtE,2BAAyB,OAAO;AAAA,IAC9B,WAAWc,EAAO;AAAA,IAClB,4BAA4BC,GAAW;AAAA,MACrC,KAAK,CAAAC,MAAQ;AACX,QAAAT,EAAS,UAAUS;AAAA,MACrB;AAAA,MACA,OAAOL;AAAA,MACP,UAAU,CAAAM,MAAQhB,EAAUiB,EAAeD,CAAI,CAAC;AAAA,MAChD,WAAAb;AAAA,MACA,WAAAE;AAAA,MACA,WAAW;AAAA,MACX,aAAAH;AAAA,MACA,WAAWW,EAAO;AAAA,MAClB,cAAcX;AAAA,MACd,eAAAE;AAAA,MACA,UAAU,MAAMH,EAAA;AAAA,MAChB,cAAc,CAAAiB,MAASX,EAASW,CAAK;AAAA,MACrC,aAAaV;AAAA,IAAA,CACd;AAAA,EAAA,CACF;AACH;"}
@@ -0,0 +1,44 @@
1
+ import { type ReactNode, type RefObject } from 'react';
2
+ import { useFileDrag } from '../hooks/useFileDrag';
3
+ import type { ComposerUploadResult, ComposerValue } from './types';
4
+ export type ComposerFieldHandle = {
5
+ focus: () => void;
6
+ };
7
+ export type ComposerContextValue = {
8
+ value: ComposerValue;
9
+ setPrompt: (prompt: string) => void;
10
+ setPlanMode: (planMode: boolean) => void;
11
+ addFiles: (files: FileList | readonly File[]) => void;
12
+ removeAttachment: (clientId: string) => void;
13
+ retryAttachment: (clientId: string) => void;
14
+ submit: () => void;
15
+ canSubmit: boolean;
16
+ busy: boolean;
17
+ placeholder: string;
18
+ autoFocus: boolean;
19
+ submitOnEnter: boolean;
20
+ rows: number;
21
+ minHeight: number;
22
+ pasteTextAsFile: (text: string) => boolean;
23
+ openFilePicker: () => void;
24
+ focus: () => void;
25
+ focusRef: RefObject<ComposerFieldHandle | null>;
26
+ fileDragOver: boolean;
27
+ drag: ReturnType<typeof useFileDrag>;
28
+ };
29
+ export declare function useComposer(): ComposerContextValue;
30
+ export type ComposerProviderProps = {
31
+ value: ComposerValue;
32
+ onChange: (value: ComposerValue) => void;
33
+ onSubmit: () => void;
34
+ uploadFile: (file: File) => Promise<ComposerUploadResult>;
35
+ busy?: boolean;
36
+ placeholder?: string;
37
+ autoFocus?: boolean;
38
+ submitHotkey?: 'enter' | 'mod+enter';
39
+ /** Fixed min rows for the field (create project uses 3). */
40
+ rows?: number;
41
+ children: ReactNode;
42
+ };
43
+ export declare function ComposerProvider({ value, onChange, onSubmit, uploadFile, busy, placeholder, autoFocus, submitHotkey, rows, children, }: ComposerProviderProps): import("react").JSX.Element;
44
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/Composer/context.tsx"],"names":[],"mappings":"AASA,OAAO,EAQH,KAAK,SAAS,EACd,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,KAAK,EAER,oBAAoB,EACpB,aAAa,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,mBAAmB,GAAG;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,IAAI,EAAE,KAAK,IAAI,CAAC;IACtD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CACxC,CAAC;AAIF,wBAAgB,WAAW,IAAI,oBAAoB,CAQlD;AAmCD,MAAM,MAAM,qBAAqB,GAAG;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IACrC,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,IAAY,EACZ,WAAkC,EAClC,SAAgB,EAChB,YAA0B,EAC1B,IAAQ,EACR,QAAQ,GACX,EAAE,qBAAqB,+BAgOvB"}
@@ -0,0 +1,205 @@
1
+ import { coerceUploadMimeType as z, MAX_CHAT_ATTACHMENT_BYTES_PER_FILE as y, MAX_CHAT_ATTACHMENT_BYTES_TOTAL as x, COMPOSER_PASTE_AS_FILE_MIN_CHARS as $ } from "@reforma/constants";
2
+ import { revokeObjectURL as A, formatFileSize as F, createObjectURL as X } from "@reforma/lib";
3
+ import { useRef as f, useState as Y, useLayoutEffect as W, useEffect as q, useCallback as R, use as G, createContext as J } from "react";
4
+ import { useFileDrag as K } from "../hooks/useFileDrag.js";
5
+ import { toast as T } from "../Toast/Toast.js";
6
+ import { jsxs as Q, jsx as V } from "react/jsx-runtime";
7
+ const M = /* @__PURE__ */ J(null);
8
+ function it() {
9
+ const o = G(M);
10
+ if (!o)
11
+ throw new Error("Composer pieces must render inside ComposerProvider");
12
+ return o;
13
+ }
14
+ function Z(o) {
15
+ let s = 0;
16
+ for (const c of o)
17
+ typeof c.size == "number" && Number.isFinite(c.size) && (s += c.size);
18
+ return s;
19
+ }
20
+ function tt(o) {
21
+ return o.length === 0 ? !0 : o.every((s) => s.uploadStatus === "ready" && !!s.url);
22
+ }
23
+ function v(o, s, c) {
24
+ return {
25
+ ...o,
26
+ attachments: o.attachments.map((m) => m.clientId === s ? {
27
+ ...m,
28
+ ...c
29
+ } : m)
30
+ };
31
+ }
32
+ function ct({
33
+ value: o,
34
+ onChange: s,
35
+ onSubmit: c,
36
+ uploadFile: m,
37
+ busy: E = !1,
38
+ placeholder: b = "What should it do?",
39
+ autoFocus: O = !0,
40
+ submitHotkey: C = "mod+enter",
41
+ rows: h = 3,
42
+ children: P
43
+ }) {
44
+ const S = f(null), _ = f(null), i = f(o), l = f(/* @__PURE__ */ new Map()), [B, D] = Y(!1);
45
+ W(() => {
46
+ i.current = o;
47
+ }, [o]), q(() => {
48
+ const t = l.current;
49
+ return () => {
50
+ for (const n of i.current.attachments)
51
+ A(n.preview);
52
+ t.clear();
53
+ };
54
+ }, []);
55
+ const w = !!o.prompt.trim() && tt(o.attachments) && !E, g = R(async (t, n) => {
56
+ const r = await m(n), a = i.current;
57
+ if (!a.attachments.some((u) => u.clientId === t)) {
58
+ l.current.delete(t);
59
+ return;
60
+ }
61
+ if (r.ok) {
62
+ const u = a.attachments.find((d) => d.clientId === t)?.preview;
63
+ A(u), l.current.delete(t), s(v(a, t, {
64
+ id: r.data.id,
65
+ url: r.data.url,
66
+ filename: r.data.name ?? n.name,
67
+ mediaType: r.data.mimeType ?? z(n.name, n.type),
68
+ size: r.data.size ?? n.size,
69
+ uploadStatus: "ready",
70
+ uploadError: void 0,
71
+ preview: void 0
72
+ }));
73
+ return;
74
+ }
75
+ s(v(a, t, {
76
+ uploadStatus: "error",
77
+ uploadError: r.message ?? "Upload failed"
78
+ }));
79
+ }, [s, m]), p = R((t) => {
80
+ const n = [...t], r = [];
81
+ let a = 0;
82
+ const u = Z(i.current.attachments);
83
+ for (const e of n) {
84
+ if (e.size > y) {
85
+ T.warning({
86
+ title: "Attachment too large",
87
+ message: `${e.name} is over the ${F(y, {
88
+ round: "up"
89
+ })} per-file limit.`
90
+ });
91
+ continue;
92
+ }
93
+ if (u + a + e.size > x) {
94
+ T.warning({
95
+ title: "Attachments too large",
96
+ message: `Adding ${e.name} would exceed the ${F(x, {
97
+ round: "up"
98
+ })} combined limit.`
99
+ });
100
+ continue;
101
+ }
102
+ r.push(e), a += e.size;
103
+ }
104
+ if (r.length === 0)
105
+ return;
106
+ const d = r.map((e) => ({
107
+ clientId: crypto.randomUUID(),
108
+ filename: e.name,
109
+ mediaType: z(e.name, e.type),
110
+ size: e.size,
111
+ lastModified: e.lastModified,
112
+ uploadStatus: "uploading",
113
+ preview: X(e) ?? void 0
114
+ }));
115
+ for (let e = 0; e < r.length; e++)
116
+ l.current.set(d[e].clientId, r[e]);
117
+ const N = {
118
+ ...i.current,
119
+ attachments: [...i.current.attachments, ...d]
120
+ };
121
+ s(N);
122
+ for (let e = 0; e < r.length; e++)
123
+ g(d[e].clientId, r[e]);
124
+ }, [s, g]), H = K({
125
+ onFileDragOver: D,
126
+ onFilesDropped: (t) => p(t)
127
+ }), I = (t) => {
128
+ const n = i.current, r = n.attachments.find((a) => a.clientId === t);
129
+ A(r?.preview), l.current.delete(t), s({
130
+ ...n,
131
+ attachments: n.attachments.filter((a) => a.clientId !== t)
132
+ });
133
+ }, L = (t) => {
134
+ const n = i.current, r = n.attachments.find((u) => u.clientId === t), a = l.current.get(t);
135
+ if (!(!r || r.uploadStatus !== "error")) {
136
+ if (!a) {
137
+ T.warning({
138
+ title: "Could not retry",
139
+ message: "Remove the file and attach it again."
140
+ });
141
+ return;
142
+ }
143
+ s(v(n, t, {
144
+ uploadStatus: "uploading",
145
+ uploadError: void 0
146
+ })), g(t, a);
147
+ }
148
+ }, U = () => {
149
+ w && c();
150
+ }, k = (t) => {
151
+ if (t.length < $)
152
+ return !1;
153
+ const n = new File([t], "paste.txt", {
154
+ type: "text/plain"
155
+ });
156
+ return n.size > y ? !1 : (p([n]), !0);
157
+ }, j = {
158
+ value: o,
159
+ setPrompt: (t) => s({
160
+ ...i.current,
161
+ prompt: t
162
+ }),
163
+ setPlanMode: (t) => s({
164
+ ...i.current,
165
+ planMode: t
166
+ }),
167
+ addFiles: p,
168
+ removeAttachment: I,
169
+ retryAttachment: L,
170
+ submit: U,
171
+ canSubmit: w,
172
+ busy: E,
173
+ placeholder: b,
174
+ autoFocus: O,
175
+ submitOnEnter: C === "enter",
176
+ rows: h,
177
+ minHeight: h ? h * 22 : 20,
178
+ pasteTextAsFile: k,
179
+ openFilePicker: () => S.current?.click(),
180
+ focus: () => _.current?.focus(),
181
+ focusRef: _,
182
+ fileDragOver: B,
183
+ drag: H
184
+ };
185
+ return /* @__PURE__ */ Q(M, {
186
+ value: j,
187
+ children: [P, /* @__PURE__ */ V("input", {
188
+ ref: S,
189
+ type: "file",
190
+ multiple: !0,
191
+ tabIndex: -1,
192
+ style: {
193
+ display: "none"
194
+ },
195
+ onChange: (t) => {
196
+ t.target.files?.length && p(t.target.files), t.target.value = "";
197
+ }
198
+ })]
199
+ });
200
+ }
201
+ export {
202
+ ct as ComposerProvider,
203
+ it as useComposer
204
+ };
205
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sources":["../../src/Composer/context.tsx"],"sourcesContent":["'use client';\n\nimport {\n coerceUploadMimeType,\n COMPOSER_PASTE_AS_FILE_MIN_CHARS,\n MAX_CHAT_ATTACHMENT_BYTES_PER_FILE,\n MAX_CHAT_ATTACHMENT_BYTES_TOTAL,\n} from '@reforma/constants';\nimport { createObjectURL, formatFileSize, revokeObjectURL } from '@reforma/lib';\nimport {\n createContext,\n use,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from 'react';\n\nimport { useFileDrag } from '../hooks/useFileDrag';\nimport { toast } from '../Toast';\n\nimport type {\n ComposerAttachment,\n ComposerUploadResult,\n ComposerValue,\n} from './types';\n\nexport type ComposerFieldHandle = {\n focus: () => void;\n};\n\nexport type ComposerContextValue = {\n value: ComposerValue;\n setPrompt: (prompt: string) => void;\n setPlanMode: (planMode: boolean) => void;\n addFiles: (files: FileList | readonly File[]) => void;\n removeAttachment: (clientId: string) => void;\n retryAttachment: (clientId: string) => void;\n submit: () => void;\n canSubmit: boolean;\n busy: boolean;\n placeholder: string;\n autoFocus: boolean;\n submitOnEnter: boolean;\n rows: number;\n minHeight: number;\n pasteTextAsFile: (text: string) => boolean;\n openFilePicker: () => void;\n focus: () => void;\n focusRef: RefObject<ComposerFieldHandle | null>;\n fileDragOver: boolean;\n drag: ReturnType<typeof useFileDrag>;\n};\n\nconst ComposerContext = createContext<ComposerContextValue | null>(null);\n\nexport function useComposer(): ComposerContextValue {\n const context = use(ComposerContext);\n\n if (!context) {\n throw new Error('Composer pieces must render inside ComposerProvider');\n }\n\n return context;\n}\n\nfunction sumAttachmentBytes(items: readonly ComposerAttachment[]): number {\n let sum = 0;\n\n for (const item of items) {\n if (typeof item.size === 'number' && Number.isFinite(item.size)) {\n sum += item.size;\n }\n }\n\n return sum;\n}\n\nfunction attachmentsReady(items: readonly ComposerAttachment[]): boolean {\n if (items.length === 0) {\n return true;\n }\n\n return items.every(item => item.uploadStatus === 'ready' && Boolean(item.url));\n}\n\nfunction patchAttachment(\n value: ComposerValue,\n clientId: string,\n patch: Partial<ComposerAttachment>\n): ComposerValue {\n return {\n ...value,\n attachments: value.attachments.map(item => (\n item.clientId === clientId ? { ...item, ...patch } : item\n )),\n };\n}\n\nexport type ComposerProviderProps = {\n value: ComposerValue;\n onChange: (value: ComposerValue) => void;\n onSubmit: () => void;\n uploadFile: (file: File) => Promise<ComposerUploadResult>;\n busy?: boolean;\n placeholder?: string;\n autoFocus?: boolean;\n submitHotkey?: 'enter' | 'mod+enter';\n /** Fixed min rows for the field (create project uses 3). */\n rows?: number;\n children: ReactNode;\n};\n\nexport function ComposerProvider({\n value,\n onChange,\n onSubmit,\n uploadFile,\n busy = false,\n placeholder = 'What should it do?',\n autoFocus = true,\n submitHotkey = 'mod+enter',\n rows = 3,\n children,\n}: ComposerProviderProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const focusRef = useRef<ComposerFieldHandle | null>(null);\n const valueRef = useRef(value);\n const pendingFilesRef = useRef(new Map<string, File>());\n const [fileDragOver, setFileDragOver] = useState(false);\n\n useLayoutEffect(() => {\n valueRef.current = value;\n }, [value]);\n\n useEffect(() => {\n const pending = pendingFilesRef.current;\n\n return () => {\n for (const item of valueRef.current.attachments) {\n revokeObjectURL(item.preview);\n }\n\n pending.clear();\n };\n }, []);\n\n const canSubmit = Boolean(value.prompt.trim())\n && attachmentsReady(value.attachments)\n && !busy;\n\n const uploadOne = useCallback(async(clientId: string, file: File) => {\n const result = await uploadFile(file);\n const current = valueRef.current;\n\n if (!current.attachments.some(item => item.clientId === clientId)) {\n pendingFilesRef.current.delete(clientId);\n\n return;\n }\n\n if (result.ok) {\n const preview = current.attachments.find(item => item.clientId === clientId)?.preview;\n revokeObjectURL(preview);\n pendingFilesRef.current.delete(clientId);\n onChange(patchAttachment(current, clientId, {\n id: result.data.id,\n url: result.data.url,\n filename: result.data.name ?? file.name,\n mediaType: result.data.mimeType ?? coerceUploadMimeType(file.name, file.type),\n size: result.data.size ?? file.size,\n uploadStatus: 'ready',\n uploadError: undefined,\n preview: undefined,\n }));\n\n return;\n }\n\n onChange(patchAttachment(current, clientId, {\n uploadStatus: 'error',\n uploadError: result.message ?? 'Upload failed',\n }));\n }, [onChange, uploadFile]);\n\n const addFiles = useCallback((files: FileList | readonly File[]) => {\n const list = [...files];\n const accepted: File[] = [];\n let batchBytes = 0;\n const used = sumAttachmentBytes(valueRef.current.attachments);\n\n for (const file of list) {\n if (file.size > MAX_CHAT_ATTACHMENT_BYTES_PER_FILE) {\n toast.warning({\n title: 'Attachment too large',\n message: `${ file.name } is over the ${ formatFileSize(MAX_CHAT_ATTACHMENT_BYTES_PER_FILE, { round: 'up' }) } per-file limit.`,\n });\n continue;\n }\n\n if (used + batchBytes + file.size > MAX_CHAT_ATTACHMENT_BYTES_TOTAL) {\n toast.warning({\n title: 'Attachments too large',\n message: `Adding ${ file.name } would exceed the ${ formatFileSize(MAX_CHAT_ATTACHMENT_BYTES_TOTAL, { round: 'up' }) } combined limit.`,\n });\n continue;\n }\n\n accepted.push(file);\n batchBytes += file.size;\n }\n\n if (accepted.length === 0) {\n return;\n }\n\n const nextItems: ComposerAttachment[] = accepted.map(file => ({\n clientId: crypto.randomUUID(),\n filename: file.name,\n mediaType: coerceUploadMimeType(file.name, file.type),\n size: file.size,\n lastModified: file.lastModified,\n uploadStatus: 'uploading',\n preview: createObjectURL(file) ?? undefined,\n }));\n\n for (let i = 0; i < accepted.length; i++) {\n pendingFilesRef.current.set(nextItems[i]!.clientId, accepted[i]!);\n }\n\n const next: ComposerValue = {\n ...valueRef.current,\n attachments: [...valueRef.current.attachments, ...nextItems],\n };\n onChange(next);\n\n for (let i = 0; i < accepted.length; i++) {\n void uploadOne(nextItems[i]!.clientId, accepted[i]!);\n }\n }, [onChange, uploadOne]);\n\n const drag = useFileDrag({\n onFileDragOver: setFileDragOver,\n onFilesDropped: files => addFiles(files),\n });\n\n const removeAttachment = (clientId: string) => {\n const current = valueRef.current;\n const item = current.attachments.find(entry => entry.clientId === clientId);\n revokeObjectURL(item?.preview);\n pendingFilesRef.current.delete(clientId);\n onChange({\n ...current,\n attachments: current.attachments.filter(entry => entry.clientId !== clientId),\n });\n };\n\n const retryAttachment = (clientId: string) => {\n const current = valueRef.current;\n const item = current.attachments.find(entry => entry.clientId === clientId);\n const file = pendingFilesRef.current.get(clientId);\n\n if (!item || item.uploadStatus !== 'error') {\n return;\n }\n\n if (!file) {\n toast.warning({\n title: 'Could not retry',\n message: 'Remove the file and attach it again.',\n });\n\n return;\n }\n\n onChange(patchAttachment(current, clientId, {\n uploadStatus: 'uploading',\n uploadError: undefined,\n }));\n void uploadOne(clientId, file);\n };\n\n const submit = () => {\n if (!canSubmit) {\n return;\n }\n\n onSubmit();\n };\n\n const pasteTextAsFile = (text: string) => {\n if (text.length < COMPOSER_PASTE_AS_FILE_MIN_CHARS) {\n return false;\n }\n\n const file = new File([text], 'paste.txt', { type: 'text/plain' });\n\n if (file.size > MAX_CHAT_ATTACHMENT_BYTES_PER_FILE) {\n return false;\n }\n\n addFiles([file]);\n\n return true;\n };\n\n const api: ComposerContextValue = {\n value,\n setPrompt: (prompt) => onChange({ ...valueRef.current, prompt }),\n setPlanMode: (planMode) => onChange({ ...valueRef.current, planMode }),\n addFiles,\n removeAttachment,\n retryAttachment,\n submit,\n canSubmit,\n busy,\n placeholder,\n autoFocus,\n submitOnEnter: submitHotkey === 'enter',\n rows,\n minHeight: rows ? rows * 22 : 20,\n pasteTextAsFile,\n openFilePicker: () => fileInputRef.current?.click(),\n focus: () => focusRef.current?.focus(),\n focusRef,\n fileDragOver,\n drag,\n };\n\n return (\n <ComposerContext value={ api }>\n { children }\n <input\n ref={ fileInputRef }\n type=\"file\"\n multiple\n tabIndex={ -1 }\n style={ { display: 'none' } }\n onChange={ (event) => {\n if (event.target.files?.length) {\n addFiles(event.target.files);\n }\n\n event.target.value = '';\n } }\n />\n </ComposerContext>\n );\n}\n"],"names":["ComposerContext","useComposer","context","use","sumAttachmentBytes","items","sum","item","attachmentsReady","patchAttachment","value","clientId","patch","ComposerProvider","onChange","onSubmit","uploadFile","busy","placeholder","autoFocus","submitHotkey","rows","children","fileInputRef","useRef","focusRef","valueRef","pendingFilesRef","fileDragOver","setFileDragOver","useState","useLayoutEffect","useEffect","pending","revokeObjectURL","canSubmit","uploadOne","useCallback","file","result","current","preview","coerceUploadMimeType","addFiles","files","list","accepted","batchBytes","used","MAX_CHAT_ATTACHMENT_BYTES_PER_FILE","toast","formatFileSize","MAX_CHAT_ATTACHMENT_BYTES_TOTAL","nextItems","createObjectURL","i","next","drag","useFileDrag","removeAttachment","entry","retryAttachment","submit","pasteTextAsFile","text","COMPOSER_PASTE_AS_FILE_MIN_CHARS","api","prompt","planMode","_jsx","event"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { ComposerProvider, useComposer, type ComposerContextValue, type ComposerFieldHandle, type ComposerProviderProps, } from './context';
2
+ export { ComposerAttachments, ComposerFileButton, ComposerFrame, ComposerPlan, ComposerSubmit, ComposerSurface, ComposerTextarea, ComposerToolbar, ComposerTools, } from './parts';
3
+ export { ComposerRichField } from './RichField';
4
+ export type { ComposerAttachment, ComposerUploadErr, ComposerUploadOk, ComposerUploadResult, ComposerValue, } from './types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Composer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,gBAAgB,EAChB,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,GAC7B,MAAM,WAAW,CAAC;AACnB,OAAO,EACH,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,GAChB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EACR,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,GAChB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { ComposerProvider as r, useComposer as m } from "./context.js";
2
+ import { ComposerAttachments as s, ComposerFileButton as C, ComposerFrame as t, ComposerPlan as a, ComposerSubmit as i, ComposerSurface as l, ComposerTextarea as f, ComposerToolbar as u, ComposerTools as x } from "./parts.js";
3
+ import { ComposerRichField as n } from "./RichField.js";
4
+ export {
5
+ s as ComposerAttachments,
6
+ C as ComposerFileButton,
7
+ t as ComposerFrame,
8
+ a as ComposerPlan,
9
+ r as ComposerProvider,
10
+ n as ComposerRichField,
11
+ i as ComposerSubmit,
12
+ l as ComposerSurface,
13
+ f as ComposerTextarea,
14
+ u as ComposerToolbar,
15
+ x as ComposerTools,
16
+ m as useComposer
17
+ };
18
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from 'react';
2
+ export declare function ComposerFrame({ className, children, }: {
3
+ className?: string;
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
6
+ /** Relative row that pins the tools and the submit button to the field. */
7
+ export declare function ComposerSurface({ children }: {
8
+ children: ReactNode;
9
+ }): import("react").JSX.Element;
10
+ /** Left cluster: file button, plan, whatever else you drop in. */
11
+ export declare function ComposerTools({ children }: {
12
+ children: ReactNode;
13
+ }): import("react").JSX.Element;
14
+ export declare function ComposerToolbar({ children }: {
15
+ children?: ReactNode;
16
+ }): import("react").JSX.Element;
17
+ export declare function ComposerAttachments(): import("react").JSX.Element;
18
+ export declare function ComposerFileButton(): import("react").JSX.Element;
19
+ export declare function ComposerPlan(): import("react").JSX.Element;
20
+ export declare function ComposerTextarea(): import("react").JSX.Element;
21
+ export declare function ComposerSubmit(): import("react").JSX.Element;
22
+ //# sourceMappingURL=parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../src/Composer/parts.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAW3D,wBAAgB,aAAa,CAAC,EAC1B,SAAS,EACT,QAAQ,GACX,EAAE;IACC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACvB,+BAkBA;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAkBpE;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAMlE;AAED,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAQrE;AAED,wBAAgB,mBAAmB,gCA8BlC;AAED,wBAAgB,kBAAkB,gCAiBjC;AAED,wBAAgB,YAAY,gCAsC3B;AAED,wBAAgB,gBAAgB,gCAsD/B;AAED,wBAAgB,cAAc,gCAmB7B"}