@knkcs/anker 0.0.3 → 0.0.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 (43) hide show
  1. package/dist/atoms/index.d.ts +16 -3
  2. package/dist/atoms/index.js +89 -6
  3. package/dist/atoms/index.js.map +1 -1
  4. package/dist/chunk-5YDCDC4B.js +12 -0
  5. package/dist/chunk-5YDCDC4B.js.map +1 -0
  6. package/dist/{chunk-C4JI3JNA.js → chunk-6H4LQUMM.js} +4 -33
  7. package/dist/chunk-6H4LQUMM.js.map +1 -0
  8. package/dist/{chunk-PZCL4M6I.js → chunk-E7KRPPCQ.js} +5 -18
  9. package/dist/chunk-E7KRPPCQ.js.map +1 -0
  10. package/dist/{chunk-GJTQLZ4O.js → chunk-KVPN6T6J.js} +6 -28
  11. package/dist/chunk-KVPN6T6J.js.map +1 -0
  12. package/dist/chunk-OU6H3KU4.js +21 -0
  13. package/dist/chunk-OU6H3KU4.js.map +1 -0
  14. package/dist/chunk-SJ6YXNZW.js +30 -0
  15. package/dist/chunk-SJ6YXNZW.js.map +1 -0
  16. package/dist/chunk-SJIYWHIV.js +51 -0
  17. package/dist/chunk-SJIYWHIV.js.map +1 -0
  18. package/dist/chunk-WEP2AIQ5.js +37 -0
  19. package/dist/chunk-WEP2AIQ5.js.map +1 -0
  20. package/dist/chunk-WQIEF5N3.js +52 -0
  21. package/dist/chunk-WQIEF5N3.js.map +1 -0
  22. package/dist/{chunk-QU3FF5WI.js → chunk-ZFBDVERP.js} +4 -8
  23. package/dist/chunk-ZFBDVERP.js.map +1 -0
  24. package/dist/components/index.d.ts +171 -3
  25. package/dist/components/index.js +685 -11
  26. package/dist/components/index.js.map +1 -1
  27. package/dist/feedback/index.d.ts +20 -1
  28. package/dist/feedback/index.js +121 -4
  29. package/dist/feedback/index.js.map +1 -1
  30. package/dist/forms/index.d.ts +23 -15
  31. package/dist/forms/index.js +71 -47
  32. package/dist/forms/index.js.map +1 -1
  33. package/dist/primitives/index.js +8 -49
  34. package/dist/primitives/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-7UJ4QEUW.js +0 -37
  37. package/dist/chunk-7UJ4QEUW.js.map +0 -1
  38. package/dist/chunk-C4JI3JNA.js.map +0 -1
  39. package/dist/chunk-GJTQLZ4O.js.map +0 -1
  40. package/dist/chunk-PZCL4M6I.js.map +0 -1
  41. package/dist/chunk-QU3FF5WI.js.map +0 -1
  42. package/dist/chunk-RJPEVNMJ.js +0 -23
  43. package/dist/chunk-RJPEVNMJ.js.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { ButtonProps } from '@chakra-ui/react';
2
2
  import React__default from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  interface ConfirmOptions {
5
6
  /** Dialog title text. */
@@ -24,4 +25,22 @@ interface ConfirmModalProviderProps {
24
25
  declare const ConfirmModalProvider: React__default.FC<ConfirmModalProviderProps>;
25
26
  declare const useConfirmModal: () => ConfirmModalContextType;
26
27
 
27
- export { ConfirmModalProvider, type ConfirmOptions, useConfirmModal };
28
+ interface UploadFileStatus {
29
+ id: string;
30
+ filename: string;
31
+ status: "pending" | "uploading" | "processing" | "done" | "error";
32
+ progress?: number;
33
+ error?: string;
34
+ }
35
+ interface UploadToastStackProps {
36
+ files: UploadFileStatus[];
37
+ onDismiss: () => void;
38
+ autoDismissMs?: number;
39
+ defaultExpanded?: boolean;
40
+ }
41
+ declare const UploadToastStack: {
42
+ ({ files, onDismiss, autoDismissMs, defaultExpanded, }: UploadToastStackProps): react_jsx_runtime.JSX.Element | null;
43
+ displayName: string;
44
+ };
45
+
46
+ export { ConfirmModalProvider, type ConfirmOptions, type UploadFileStatus, UploadToastStack, type UploadToastStackProps, useConfirmModal };
@@ -1,8 +1,11 @@
1
- import { Dialog, Portal, ButtonGroup, Button } from '@chakra-ui/react';
2
- import { createContext, useState, useRef, useCallback, useContext } from 'react';
1
+ import { Progress } from '../chunk-WEP2AIQ5.js';
2
+ import { Spinner } from '../chunk-5YDCDC4B.js';
3
+ import { IconButton } from '../chunk-SJ6YXNZW.js';
4
+ import { Dialog, Portal, ButtonGroup, Button, Box, Flex, Text, Stack, HStack } from '@chakra-ui/react';
5
+ import { createContext, useState, useRef, useCallback, useContext, useEffect } from 'react';
3
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
+ import { ChevronDown, ChevronUp, X, AlertCircle, Check, Clock } from 'lucide-react';
4
8
 
5
- // src/feedback/confirm-modal.tsx
6
9
  var ConfirmModalContext = createContext(
7
10
  void 0
8
11
  );
@@ -94,7 +97,121 @@ var ConfirmModalDialog = ({
94
97
  }
95
98
  );
96
99
  };
100
+ var FileStatusIcon = ({ status }) => {
101
+ switch (status) {
102
+ case "pending":
103
+ return /* @__PURE__ */ jsx(Clock, { size: 14, color: "var(--chakra-colors-fg-muted)" });
104
+ case "uploading":
105
+ case "processing":
106
+ return /* @__PURE__ */ jsx(Spinner, { size: "xs" });
107
+ case "done":
108
+ return /* @__PURE__ */ jsx(Check, { size: 14, color: "var(--chakra-colors-green-500)" });
109
+ case "error":
110
+ return /* @__PURE__ */ jsx(AlertCircle, { size: 14, color: "var(--chakra-colors-red-500)" });
111
+ }
112
+ };
113
+ var UploadToastStack = ({
114
+ files,
115
+ onDismiss,
116
+ autoDismissMs = 5e3,
117
+ defaultExpanded = true
118
+ }) => {
119
+ const [expanded, setExpanded] = useState(defaultExpanded);
120
+ const [hovered, setHovered] = useState(false);
121
+ const allComplete = files.every(
122
+ (f) => f.status === "done" || f.status === "error"
123
+ );
124
+ const totalProgress = files.length > 0 ? files.reduce((sum, f) => sum + (f.progress ?? 0), 0) / files.length : 0;
125
+ const doneCount = files.filter((f) => f.status === "done").length;
126
+ const errorCount = files.filter((f) => f.status === "error").length;
127
+ const headerText = allComplete ? `${doneCount} file${doneCount !== 1 ? "s" : ""} uploaded${errorCount > 0 ? `, ${errorCount} failed` : ""}` : `Uploading ${files.length} file${files.length !== 1 ? "s" : ""}...`;
128
+ useEffect(() => {
129
+ if (!allComplete || hovered || autoDismissMs === 0) return;
130
+ const timer = setTimeout(onDismiss, autoDismissMs);
131
+ return () => clearTimeout(timer);
132
+ }, [allComplete, hovered, autoDismissMs, onDismiss]);
133
+ if (files.length === 0) return null;
134
+ return /* @__PURE__ */ jsx(
135
+ Box,
136
+ {
137
+ position: "fixed",
138
+ bottom: 4,
139
+ insetInlineEnd: 4,
140
+ zIndex: "toast",
141
+ onMouseEnter: () => setHovered(true),
142
+ onMouseLeave: () => setHovered(false),
143
+ children: /* @__PURE__ */ jsxs(
144
+ Box,
145
+ {
146
+ bg: "bg.surface",
147
+ shadow: "lg",
148
+ rounded: "lg",
149
+ borderWidth: "1px",
150
+ borderColor: "border",
151
+ w: "320px",
152
+ overflow: "hidden",
153
+ children: [
154
+ /* @__PURE__ */ jsxs(Flex, { align: "center", px: 3, py: 2, gap: 1, children: [
155
+ /* @__PURE__ */ jsx(Text, { fontSize: "sm", fontWeight: "medium", flex: "1", children: headerText }),
156
+ /* @__PURE__ */ jsx(
157
+ IconButton,
158
+ {
159
+ "aria-label": expanded ? "Collapse upload list" : "Expand upload list",
160
+ size: "xs",
161
+ variant: "ghost",
162
+ onClick: () => setExpanded((v) => !v),
163
+ children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronUp, { size: 14 })
164
+ }
165
+ ),
166
+ /* @__PURE__ */ jsx(
167
+ IconButton,
168
+ {
169
+ "aria-label": "Dismiss upload toast",
170
+ size: "xs",
171
+ variant: "ghost",
172
+ onClick: onDismiss,
173
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
174
+ }
175
+ )
176
+ ] }),
177
+ /* @__PURE__ */ jsx(
178
+ Progress,
179
+ {
180
+ value: totalProgress,
181
+ size: "xs",
182
+ colorPalette: allComplete && errorCount === 0 ? "green" : "primary"
183
+ }
184
+ ),
185
+ expanded && /* @__PURE__ */ jsx(Stack, { gap: 0, maxH: "200px", overflowY: "auto", px: 3, py: 2, children: files.map((file) => /* @__PURE__ */ jsxs(Box, { py: 1, children: [
186
+ /* @__PURE__ */ jsxs(HStack, { gap: 2, align: "center", children: [
187
+ /* @__PURE__ */ jsx(Box, { flexShrink: 0, children: /* @__PURE__ */ jsx(FileStatusIcon, { status: file.status }) }),
188
+ /* @__PURE__ */ jsx(
189
+ Text,
190
+ {
191
+ fontSize: "sm",
192
+ flex: "1",
193
+ overflow: "hidden",
194
+ textOverflow: "ellipsis",
195
+ whiteSpace: "nowrap",
196
+ title: file.filename,
197
+ children: file.filename
198
+ }
199
+ ),
200
+ file.progress !== void 0 && /* @__PURE__ */ jsxs(Text, { fontSize: "xs", color: "fg.muted", flexShrink: 0, children: [
201
+ Math.round(file.progress),
202
+ "%"
203
+ ] })
204
+ ] }),
205
+ file.status === "error" && file.error && /* @__PURE__ */ jsx(Text, { fontSize: "xs", color: "fg.error", ps: 5, children: file.error })
206
+ ] }, file.id)) })
207
+ ]
208
+ }
209
+ )
210
+ }
211
+ );
212
+ };
213
+ UploadToastStack.displayName = "UploadToastStack";
97
214
 
98
- export { ConfirmModalProvider, useConfirmModal };
215
+ export { ConfirmModalProvider, UploadToastStack, useConfirmModal };
99
216
  //# sourceMappingURL=index.js.map
100
217
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feedback/confirm-modal.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n\tButton,\n\tButtonGroup,\n\ttype ButtonProps,\n\tDialog,\n\tPortal,\n} from \"@chakra-ui/react\";\nimport type React from \"react\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nexport interface ConfirmOptions {\n\t/** Dialog title text. */\n\ttitle: string;\n\t/** Dialog body content. */\n\tmessage: React.ReactNode;\n\t/** Label for the confirm button. @default \"Confirm\" */\n\tconfirmLabel?: string;\n\t/** Label for the cancel button. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Color palette for the confirm button. @default \"red\" */\n\tcolorPalette?: ButtonProps[\"colorPalette\"];\n\t/** Extra actions rendered before the confirm button. */\n\tbeforeConfirmActions?: React.ReactNode;\n}\n\ninterface ConfirmModalContextType {\n\tconfirm: (options: ConfirmOptions) => Promise<boolean>;\n}\n\nconst ConfirmModalContext = createContext<ConfirmModalContextType | undefined>(\n\tundefined,\n);\n\ninterface ConfirmModalProviderProps {\n\tchildren: React.ReactNode;\n}\n\nexport const ConfirmModalProvider: React.FC<ConfirmModalProviderProps> = ({\n\tchildren,\n}) => {\n\tconst [open, setOpen] = useState(false);\n\tconst [options, setOptions] = useState<ConfirmOptions>({\n\t\ttitle: \"\",\n\t\tmessage: \"\",\n\t});\n\tconst resolveRef = useRef<((value: boolean) => void) | null>(null);\n\n\tconst confirm = useCallback((opts: ConfirmOptions): Promise<boolean> => {\n\t\tsetOptions(opts);\n\t\tsetOpen(true);\n\t\treturn new Promise<boolean>((resolve) => {\n\t\t\tresolveRef.current = resolve;\n\t\t});\n\t}, []);\n\n\tconst handleClose = useCallback(() => {\n\t\tsetOpen(false);\n\t\tresolveRef.current?.(false);\n\t\tresolveRef.current = null;\n\t}, []);\n\n\tconst handleConfirm = useCallback(() => {\n\t\tsetOpen(false);\n\t\tresolveRef.current?.(true);\n\t\tresolveRef.current = null;\n\t}, []);\n\n\treturn (\n\t\t<ConfirmModalContext.Provider value={{ confirm }}>\n\t\t\t{children}\n\t\t\t<ConfirmModalDialog\n\t\t\t\topen={open}\n\t\t\t\toptions={options}\n\t\t\t\tonClose={handleClose}\n\t\t\t\tonConfirm={handleConfirm}\n\t\t\t/>\n\t\t</ConfirmModalContext.Provider>\n\t);\n};\n\nConfirmModalProvider.displayName = \"ConfirmModalProvider\";\n\nexport const useConfirmModal = (): ConfirmModalContextType => {\n\tconst context = useContext(ConfirmModalContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useConfirmModal must be used within a ConfirmModalProvider\",\n\t\t);\n\t}\n\treturn context;\n};\n\ninterface ConfirmModalDialogProps {\n\topen: boolean;\n\toptions: ConfirmOptions;\n\tonClose: () => void;\n\tonConfirm: () => void;\n}\n\nconst ConfirmModalDialog: React.FC<ConfirmModalDialogProps> = ({\n\topen,\n\toptions,\n\tonClose,\n\tonConfirm,\n}) => {\n\tconst cancelRef = useRef<HTMLButtonElement>(null);\n\tconst {\n\t\ttitle,\n\t\tmessage,\n\t\tconfirmLabel = \"Confirm\",\n\t\tcancelLabel = \"Cancel\",\n\t\tcolorPalette = \"red\",\n\t\tbeforeConfirmActions,\n\t} = options;\n\n\treturn (\n\t\t<Dialog.Root\n\t\t\topen={open}\n\t\t\tinitialFocusEl={() => cancelRef.current}\n\t\t\tplacement=\"center\"\n\t\t\trole=\"alertdialog\"\n\t\t\tonOpenChange={(e) => {\n\t\t\t\tif (!e.open) {\n\t\t\t\t\tonClose();\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t<Portal>\n\t\t\t\t<Dialog.Backdrop>\n\t\t\t\t\t<Dialog.Positioner>\n\t\t\t\t\t\t<Dialog.Content>\n\t\t\t\t\t\t\t<Dialog.Header fontSize=\"lg\" fontWeight=\"bold\">\n\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t</Dialog.Header>\n\t\t\t\t\t\t\t<Dialog.Body>{message}</Dialog.Body>\n\t\t\t\t\t\t\t<Dialog.Footer>\n\t\t\t\t\t\t\t\t<ButtonGroup size=\"sm\">\n\t\t\t\t\t\t\t\t\t<Button ref={cancelRef} variant=\"outline\" onClick={onClose}>\n\t\t\t\t\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t{beforeConfirmActions}\n\t\t\t\t\t\t\t\t\t<Button colorPalette={colorPalette} onClick={onConfirm}>\n\t\t\t\t\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</ButtonGroup>\n\t\t\t\t\t\t\t</Dialog.Footer>\n\t\t\t\t\t\t</Dialog.Content>\n\t\t\t\t\t</Dialog.Positioner>\n\t\t\t\t</Dialog.Backdrop>\n\t\t\t</Portal>\n\t\t</Dialog.Root>\n\t);\n};\n"]}
1
+ {"version":3,"sources":["../../src/feedback/confirm-modal.tsx","../../src/feedback/upload-toast-stack.tsx"],"names":["jsx","useState","jsxs"],"mappings":";;;;;;;;AAmCA,IAAM,mBAAA,GAAsB,aAAA;AAAA,EAC3B;AACD,CAAA;AAMO,IAAM,uBAA4D,CAAC;AAAA,EACzE;AACD,CAAA,KAAM;AACL,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA;AACtC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAyB;AAAA,IACtD,KAAA,EAAO,EAAA;AAAA,IACP,OAAA,EAAS;AAAA,GACT,CAAA;AACD,EAAA,MAAM,UAAA,GAAa,OAA0C,IAAI,CAAA;AAEjE,EAAA,MAAM,OAAA,GAAU,WAAA,CAAY,CAAC,IAAA,KAA2C;AACvE,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,IAAA,OAAO,IAAI,OAAA,CAAiB,CAAC,OAAA,KAAY;AACxC,MAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAAA,IACtB,CAAC,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACrC,IAAA,OAAA,CAAQ,KAAK,CAAA;AACb,IAAA,UAAA,CAAW,UAAU,KAAK,CAAA;AAC1B,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EACtB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgB,YAAY,MAAM;AACvC,IAAA,OAAA,CAAQ,KAAK,CAAA;AACb,IAAA,UAAA,CAAW,UAAU,IAAI,CAAA;AACzB,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EACtB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,4BACE,mBAAA,CAAoB,QAAA,EAApB,EAA6B,KAAA,EAAO,EAAE,SAAQ,EAC7C,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,SAAA,EAAW;AAAA;AAAA;AACZ,GAAA,EACD,CAAA;AAEF;AAEA,oBAAA,CAAqB,WAAA,GAAc,sBAAA;AAE5B,IAAM,kBAAkB,MAA+B;AAC7D,EAAA,MAAM,OAAA,GAAU,WAAW,mBAAmB,CAAA;AAC9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,MAAM,IAAI,KAAA;AAAA,MACT;AAAA,KACD;AAAA,EACD;AACA,EAAA,OAAO,OAAA;AACR;AASA,IAAM,qBAAwD,CAAC;AAAA,EAC9D,IAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA;AACD,CAAA,KAAM;AACL,EAAA,MAAM,SAAA,GAAY,OAA0B,IAAI,CAAA;AAChD,EAAA,MAAM;AAAA,IACL,KAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA,GAAe,SAAA;AAAA,IACf,WAAA,GAAc,QAAA;AAAA,IACd,YAAA,GAAe,KAAA;AAAA,IACf;AAAA,GACD,GAAI,OAAA;AAEJ,EAAA,uBACC,GAAA;AAAA,IAAC,MAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACA,IAAA;AAAA,MACA,cAAA,EAAgB,MAAM,SAAA,CAAU,OAAA;AAAA,MAChC,SAAA,EAAU,QAAA;AAAA,MACV,IAAA,EAAK,aAAA;AAAA,MACL,YAAA,EAAc,CAAC,CAAA,KAAM;AACpB,QAAA,IAAI,CAAC,EAAE,IAAA,EAAM;AACZ,UAAA,OAAA,EAAQ;AAAA,QACT;AAAA,MACD,CAAA;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EACA,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,QAAA,EAAP,EACA,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,UAAA,EAAP,EACA,QAAA,kBAAA,IAAA,CAAC,MAAA,CAAO,SAAP,EACA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,OAAO,MAAA,EAAP,EAAc,UAAS,IAAA,EAAK,UAAA,EAAW,QACtC,QAAA,EAAA,KAAA,EACF,CAAA;AAAA,wBACA,GAAA,CAAC,MAAA,CAAO,IAAA,EAAP,EAAa,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,4BACrB,MAAA,CAAO,MAAA,EAAP,EACA,QAAA,kBAAA,IAAA,CAAC,WAAA,EAAA,EAAY,MAAK,IAAA,EACjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,UAAO,GAAA,EAAK,SAAA,EAAW,SAAQ,SAAA,EAAU,OAAA,EAAS,SACjD,QAAA,EAAA,WAAA,EACF,CAAA;AAAA,UACC,oBAAA;AAAA,0BACD,GAAA,CAAC,MAAA,EAAA,EAAO,YAAA,EAA4B,OAAA,EAAS,WAC3C,QAAA,EAAA,YAAA,EACF;AAAA,SAAA,EACD,CAAA,EACD;AAAA,OAAA,EACD,CAAA,EACD,GACD,CAAA,EACD;AAAA;AAAA,GACD;AAEF,CAAA;ACjIA,IAAM,cAAA,GAAiB,CAAC,EAAE,MAAA,EAAO,KAA8C;AAC9E,EAAA,QAAQ,MAAA;AAAQ,IACf,KAAK,SAAA;AACJ,MAAA,uBAAOA,GAAAA,CAAC,KAAA,EAAA,EAAM,IAAA,EAAM,EAAA,EAAI,OAAM,+BAAA,EAAgC,CAAA;AAAA,IAC/D,KAAK,WAAA;AAAA,IACL,KAAK,YAAA;AACJ,MAAA,uBAAOA,GAAAA,CAAC,OAAA,EAAA,EAAQ,IAAA,EAAK,IAAA,EAAK,CAAA;AAAA,IAC3B,KAAK,MAAA;AACJ,MAAA,uBAAOA,GAAAA,CAAC,KAAA,EAAA,EAAM,IAAA,EAAM,EAAA,EAAI,OAAM,gCAAA,EAAiC,CAAA;AAAA,IAChE,KAAK,OAAA;AACJ,MAAA,uBAAOA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI,OAAM,8BAAA,EAA+B,CAAA;AAAA;AAEtE,CAAA;AAEO,IAAM,mBAAmB,CAAC;AAAA,EAChC,KAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA,GAAgB,GAAA;AAAA,EAChB,eAAA,GAAkB;AACnB,CAAA,KAA6B;AAC5B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIC,SAAS,eAAe,CAAA;AACxD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,cAAc,KAAA,CAAM,KAAA;AAAA,IACzB,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,MAAA,IAAU,EAAE,MAAA,KAAW;AAAA,GAC5C;AACA,EAAA,MAAM,gBACL,KAAA,CAAM,MAAA,GAAS,CAAA,GACZ,KAAA,CAAM,OAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,IAAO,EAAE,QAAA,IAAY,CAAA,CAAA,EAAI,CAAC,CAAA,GAAI,MAAM,MAAA,GAC7D,CAAA;AACJ,EAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,MAAM,CAAA,CAAE,MAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,OAAO,CAAA,CAAE,MAAA;AAE7D,EAAA,MAAM,UAAA,GAAa,WAAA,GAChB,CAAA,EAAG,SAAS,CAAA,KAAA,EAAQ,cAAc,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,SAAA,EAAY,UAAA,GAAa,CAAA,GAAI,KAAK,UAAU,CAAA,OAAA,CAAA,GAAY,EAAE,CAAA,CAAA,GACxG,CAAA,UAAA,EAAa,KAAA,CAAM,MAAM,CAAA,KAAA,EAAQ,KAAA,CAAM,MAAA,KAAW,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,GAAA,CAAA;AAEjE,EAAA,SAAA,CAAU,MAAM;AACf,IAAA,IAAI,CAAC,WAAA,IAAe,OAAA,IAAW,aAAA,KAAkB,CAAA,EAAG;AACpD,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,SAAA,EAAW,aAAa,CAAA;AACjD,IAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,EAChC,GAAG,CAAC,WAAA,EAAa,OAAA,EAAS,aAAA,EAAe,SAAS,CAAC,CAAA;AAEnD,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,uBACCD,GAAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACA,QAAA,EAAS,OAAA;AAAA,MACT,MAAA,EAAQ,CAAA;AAAA,MACR,cAAA,EAAgB,CAAA;AAAA,MAChB,MAAA,EAAO,OAAA;AAAA,MACP,YAAA,EAAc,MAAM,UAAA,CAAW,IAAI,CAAA;AAAA,MACnC,YAAA,EAAc,MAAM,UAAA,CAAW,KAAK,CAAA;AAAA,MAEpC,QAAA,kBAAAE,IAAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACA,EAAA,EAAG,YAAA;AAAA,UACH,MAAA,EAAO,IAAA;AAAA,UACP,OAAA,EAAQ,IAAA;AAAA,UACR,WAAA,EAAY,KAAA;AAAA,UACZ,WAAA,EAAY,QAAA;AAAA,UACZ,CAAA,EAAE,OAAA;AAAA,UACF,QAAA,EAAS,QAAA;AAAA,UAGT,QAAA,EAAA;AAAA,4BAAAA,IAAAA,CAAC,QAAK,KAAA,EAAM,QAAA,EAAS,IAAI,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,GAAA,EAAK,CAAA,EACvC,QAAA,EAAA;AAAA,8BAAAF,GAAAA,CAAC,QAAK,QAAA,EAAS,IAAA,EAAK,YAAW,QAAA,EAAS,IAAA,EAAK,KAC3C,QAAA,EAAA,UAAA,EACF,CAAA;AAAA,8BACAA,GAAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACA,YAAA,EACC,WAAW,sBAAA,GAAyB,oBAAA;AAAA,kBAErC,IAAA,EAAK,IAAA;AAAA,kBACL,OAAA,EAAQ,OAAA;AAAA,kBACR,SAAS,MAAM,WAAA,CAAY,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,kBAEnC,QAAA,EAAA,QAAA,mBAAWA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKA,GAAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,eAC9D;AAAA,8BACAA,GAAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACA,YAAA,EAAW,sBAAA;AAAA,kBACX,IAAA,EAAK,IAAA;AAAA,kBACL,OAAA,EAAQ,OAAA;AAAA,kBACR,OAAA,EAAS,SAAA;AAAA,kBAET,QAAA,kBAAAA,GAAAA,CAAC,CAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA;AACd,aAAA,EACD,CAAA;AAAA,4BAGAA,GAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACA,KAAA,EAAO,aAAA;AAAA,gBACP,IAAA,EAAK,IAAA;AAAA,gBACL,YAAA,EAAc,WAAA,IAAe,UAAA,KAAe,CAAA,GAAI,OAAA,GAAU;AAAA;AAAA,aAC3D;AAAA,YAGC,QAAA,oBACAA,GAAAA,CAAC,KAAA,EAAA,EAAM,KAAK,CAAA,EAAG,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,MAAA,EAAO,EAAA,EAAI,GAAG,EAAA,EAAI,CAAA,EACtD,gBAAM,GAAA,CAAI,CAAC,yBACXE,IAAAA,CAAC,GAAA,EAAA,EAAkB,EAAA,EAAI,CAAA,EACtB,QAAA,EAAA;AAAA,8BAAAA,IAAAA,CAAC,MAAA,EAAA,EAAO,GAAA,EAAK,CAAA,EAAG,OAAM,QAAA,EACrB,QAAA,EAAA;AAAA,gCAAAF,GAAAA,CAAC,GAAA,EAAA,EAAI,UAAA,EAAY,CAAA,EAChB,QAAA,kBAAAA,IAAC,cAAA,EAAA,EAAe,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,CAAA,EACtC,CAAA;AAAA,gCACAA,GAAAA;AAAA,kBAAC,IAAA;AAAA,kBAAA;AAAA,oBACA,QAAA,EAAS,IAAA;AAAA,oBACT,IAAA,EAAK,GAAA;AAAA,oBACL,QAAA,EAAS,QAAA;AAAA,oBACT,YAAA,EAAa,UAAA;AAAA,oBACb,UAAA,EAAW,QAAA;AAAA,oBACX,OAAO,IAAA,CAAK,QAAA;AAAA,oBAEX,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,iBACP;AAAA,gBACC,IAAA,CAAK,QAAA,KAAa,MAAA,oBAClBE,IAAAA,CAAC,IAAA,EAAA,EAAK,QAAA,EAAS,IAAA,EAAK,KAAA,EAAM,UAAA,EAAW,UAAA,EAAY,CAAA,EAC/C,QAAA,EAAA;AAAA,kBAAA,IAAA,CAAK,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,kBAAE;AAAA,iBAAA,EAC5B;AAAA,eAAA,EAEF,CAAA;AAAA,cACC,IAAA,CAAK,MAAA,KAAW,OAAA,IAAW,IAAA,CAAK,yBAChCF,GAAAA,CAAC,IAAA,EAAA,EAAK,QAAA,EAAS,MAAK,KAAA,EAAM,UAAA,EAAW,EAAA,EAAI,CAAA,EACvC,eAAK,KAAA,EACP;AAAA,aAAA,EAAA,EAxBQ,IAAA,CAAK,EA0Bf,CACA,CAAA,EACF;AAAA;AAAA;AAAA;AAEF;AAAA,GACD;AAEF;AAEA,gBAAA,CAAiB,WAAA,GAAc,kBAAA","file":"index.js","sourcesContent":["import {\n\tButton,\n\tButtonGroup,\n\ttype ButtonProps,\n\tDialog,\n\tPortal,\n} from \"@chakra-ui/react\";\nimport type React from \"react\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nexport interface ConfirmOptions {\n\t/** Dialog title text. */\n\ttitle: string;\n\t/** Dialog body content. */\n\tmessage: React.ReactNode;\n\t/** Label for the confirm button. @default \"Confirm\" */\n\tconfirmLabel?: string;\n\t/** Label for the cancel button. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Color palette for the confirm button. @default \"red\" */\n\tcolorPalette?: ButtonProps[\"colorPalette\"];\n\t/** Extra actions rendered before the confirm button. */\n\tbeforeConfirmActions?: React.ReactNode;\n}\n\ninterface ConfirmModalContextType {\n\tconfirm: (options: ConfirmOptions) => Promise<boolean>;\n}\n\nconst ConfirmModalContext = createContext<ConfirmModalContextType | undefined>(\n\tundefined,\n);\n\ninterface ConfirmModalProviderProps {\n\tchildren: React.ReactNode;\n}\n\nexport const ConfirmModalProvider: React.FC<ConfirmModalProviderProps> = ({\n\tchildren,\n}) => {\n\tconst [open, setOpen] = useState(false);\n\tconst [options, setOptions] = useState<ConfirmOptions>({\n\t\ttitle: \"\",\n\t\tmessage: \"\",\n\t});\n\tconst resolveRef = useRef<((value: boolean) => void) | null>(null);\n\n\tconst confirm = useCallback((opts: ConfirmOptions): Promise<boolean> => {\n\t\tsetOptions(opts);\n\t\tsetOpen(true);\n\t\treturn new Promise<boolean>((resolve) => {\n\t\t\tresolveRef.current = resolve;\n\t\t});\n\t}, []);\n\n\tconst handleClose = useCallback(() => {\n\t\tsetOpen(false);\n\t\tresolveRef.current?.(false);\n\t\tresolveRef.current = null;\n\t}, []);\n\n\tconst handleConfirm = useCallback(() => {\n\t\tsetOpen(false);\n\t\tresolveRef.current?.(true);\n\t\tresolveRef.current = null;\n\t}, []);\n\n\treturn (\n\t\t<ConfirmModalContext.Provider value={{ confirm }}>\n\t\t\t{children}\n\t\t\t<ConfirmModalDialog\n\t\t\t\topen={open}\n\t\t\t\toptions={options}\n\t\t\t\tonClose={handleClose}\n\t\t\t\tonConfirm={handleConfirm}\n\t\t\t/>\n\t\t</ConfirmModalContext.Provider>\n\t);\n};\n\nConfirmModalProvider.displayName = \"ConfirmModalProvider\";\n\nexport const useConfirmModal = (): ConfirmModalContextType => {\n\tconst context = useContext(ConfirmModalContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useConfirmModal must be used within a ConfirmModalProvider\",\n\t\t);\n\t}\n\treturn context;\n};\n\ninterface ConfirmModalDialogProps {\n\topen: boolean;\n\toptions: ConfirmOptions;\n\tonClose: () => void;\n\tonConfirm: () => void;\n}\n\nconst ConfirmModalDialog: React.FC<ConfirmModalDialogProps> = ({\n\topen,\n\toptions,\n\tonClose,\n\tonConfirm,\n}) => {\n\tconst cancelRef = useRef<HTMLButtonElement>(null);\n\tconst {\n\t\ttitle,\n\t\tmessage,\n\t\tconfirmLabel = \"Confirm\",\n\t\tcancelLabel = \"Cancel\",\n\t\tcolorPalette = \"red\",\n\t\tbeforeConfirmActions,\n\t} = options;\n\n\treturn (\n\t\t<Dialog.Root\n\t\t\topen={open}\n\t\t\tinitialFocusEl={() => cancelRef.current}\n\t\t\tplacement=\"center\"\n\t\t\trole=\"alertdialog\"\n\t\t\tonOpenChange={(e) => {\n\t\t\t\tif (!e.open) {\n\t\t\t\t\tonClose();\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t<Portal>\n\t\t\t\t<Dialog.Backdrop>\n\t\t\t\t\t<Dialog.Positioner>\n\t\t\t\t\t\t<Dialog.Content>\n\t\t\t\t\t\t\t<Dialog.Header fontSize=\"lg\" fontWeight=\"bold\">\n\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t</Dialog.Header>\n\t\t\t\t\t\t\t<Dialog.Body>{message}</Dialog.Body>\n\t\t\t\t\t\t\t<Dialog.Footer>\n\t\t\t\t\t\t\t\t<ButtonGroup size=\"sm\">\n\t\t\t\t\t\t\t\t\t<Button ref={cancelRef} variant=\"outline\" onClick={onClose}>\n\t\t\t\t\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t{beforeConfirmActions}\n\t\t\t\t\t\t\t\t\t<Button colorPalette={colorPalette} onClick={onConfirm}>\n\t\t\t\t\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</ButtonGroup>\n\t\t\t\t\t\t\t</Dialog.Footer>\n\t\t\t\t\t\t</Dialog.Content>\n\t\t\t\t\t</Dialog.Positioner>\n\t\t\t\t</Dialog.Backdrop>\n\t\t\t</Portal>\n\t\t</Dialog.Root>\n\t);\n};\n","import { Box, Flex, HStack, Stack, Text } from \"@chakra-ui/react\";\nimport {\n\tAlertCircle,\n\tCheck,\n\tChevronDown,\n\tChevronUp,\n\tClock,\n\tX,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { IconButton } from \"../atoms/button\";\nimport { Progress } from \"../primitives/progress\";\nimport { Spinner } from \"../primitives/spinner\";\n\nexport interface UploadFileStatus {\n\tid: string;\n\tfilename: string;\n\tstatus: \"pending\" | \"uploading\" | \"processing\" | \"done\" | \"error\";\n\tprogress?: number;\n\terror?: string;\n}\n\nexport interface UploadToastStackProps {\n\tfiles: UploadFileStatus[];\n\tonDismiss: () => void;\n\tautoDismissMs?: number;\n\tdefaultExpanded?: boolean;\n}\n\nconst FileStatusIcon = ({ status }: { status: UploadFileStatus[\"status\"] }) => {\n\tswitch (status) {\n\t\tcase \"pending\":\n\t\t\treturn <Clock size={14} color=\"var(--chakra-colors-fg-muted)\" />;\n\t\tcase \"uploading\":\n\t\tcase \"processing\":\n\t\t\treturn <Spinner size=\"xs\" />;\n\t\tcase \"done\":\n\t\t\treturn <Check size={14} color=\"var(--chakra-colors-green-500)\" />;\n\t\tcase \"error\":\n\t\t\treturn <AlertCircle size={14} color=\"var(--chakra-colors-red-500)\" />;\n\t}\n};\n\nexport const UploadToastStack = ({\n\tfiles,\n\tonDismiss,\n\tautoDismissMs = 5000,\n\tdefaultExpanded = true,\n}: UploadToastStackProps) => {\n\tconst [expanded, setExpanded] = useState(defaultExpanded);\n\tconst [hovered, setHovered] = useState(false);\n\n\tconst allComplete = files.every(\n\t\t(f) => f.status === \"done\" || f.status === \"error\",\n\t);\n\tconst totalProgress =\n\t\tfiles.length > 0\n\t\t\t? files.reduce((sum, f) => sum + (f.progress ?? 0), 0) / files.length\n\t\t\t: 0;\n\tconst doneCount = files.filter((f) => f.status === \"done\").length;\n\tconst errorCount = files.filter((f) => f.status === \"error\").length;\n\n\tconst headerText = allComplete\n\t\t? `${doneCount} file${doneCount !== 1 ? \"s\" : \"\"} uploaded${errorCount > 0 ? `, ${errorCount} failed` : \"\"}`\n\t\t: `Uploading ${files.length} file${files.length !== 1 ? \"s\" : \"\"}...`;\n\n\tuseEffect(() => {\n\t\tif (!allComplete || hovered || autoDismissMs === 0) return;\n\t\tconst timer = setTimeout(onDismiss, autoDismissMs);\n\t\treturn () => clearTimeout(timer);\n\t}, [allComplete, hovered, autoDismissMs, onDismiss]);\n\n\tif (files.length === 0) return null;\n\n\treturn (\n\t\t<Box\n\t\t\tposition=\"fixed\"\n\t\t\tbottom={4}\n\t\t\tinsetInlineEnd={4}\n\t\t\tzIndex=\"toast\"\n\t\t\tonMouseEnter={() => setHovered(true)}\n\t\t\tonMouseLeave={() => setHovered(false)}\n\t\t>\n\t\t\t<Box\n\t\t\t\tbg=\"bg.surface\"\n\t\t\t\tshadow=\"lg\"\n\t\t\t\trounded=\"lg\"\n\t\t\t\tborderWidth=\"1px\"\n\t\t\t\tborderColor=\"border\"\n\t\t\t\tw=\"320px\"\n\t\t\t\toverflow=\"hidden\"\n\t\t\t>\n\t\t\t\t{/* Header */}\n\t\t\t\t<Flex align=\"center\" px={3} py={2} gap={1}>\n\t\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" flex=\"1\">\n\t\t\t\t\t\t{headerText}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\texpanded ? \"Collapse upload list\" : \"Expand upload list\"\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tonClick={() => setExpanded((v) => !v)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{expanded ? <ChevronDown size={14} /> : <ChevronUp size={14} />}\n\t\t\t\t\t</IconButton>\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\taria-label=\"Dismiss upload toast\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tonClick={onDismiss}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X size={14} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t</Flex>\n\n\t\t\t\t{/* Overall progress bar */}\n\t\t\t\t<Progress\n\t\t\t\t\tvalue={totalProgress}\n\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\tcolorPalette={allComplete && errorCount === 0 ? \"green\" : \"primary\"}\n\t\t\t\t/>\n\n\t\t\t\t{/* Per-file list */}\n\t\t\t\t{expanded && (\n\t\t\t\t\t<Stack gap={0} maxH=\"200px\" overflowY=\"auto\" px={3} py={2}>\n\t\t\t\t\t\t{files.map((file) => (\n\t\t\t\t\t\t\t<Box key={file.id} py={1}>\n\t\t\t\t\t\t\t\t<HStack gap={2} align=\"center\">\n\t\t\t\t\t\t\t\t\t<Box flexShrink={0}>\n\t\t\t\t\t\t\t\t\t\t<FileStatusIcon status={file.status} />\n\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tflex=\"1\"\n\t\t\t\t\t\t\t\t\t\toverflow=\"hidden\"\n\t\t\t\t\t\t\t\t\t\ttextOverflow=\"ellipsis\"\n\t\t\t\t\t\t\t\t\t\twhiteSpace=\"nowrap\"\n\t\t\t\t\t\t\t\t\t\ttitle={file.filename}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{file.filename}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t{file.progress !== undefined && (\n\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\" flexShrink={0}>\n\t\t\t\t\t\t\t\t\t\t\t{Math.round(file.progress)}%\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t{file.status === \"error\" && file.error && (\n\t\t\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.error\" ps={5}>\n\t\t\t\t\t\t\t\t\t\t{file.error}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t</Box>\n\t);\n};\n\nUploadToastStack.displayName = \"UploadToastStack\";\n"]}
@@ -135,20 +135,6 @@ interface DirtyFormGuardProps {
135
135
  }
136
136
  declare const DirtyFormGuard: React__default.FC<DirtyFormGuardProps>;
137
137
 
138
- interface EditableHeadingProps {
139
- value?: string;
140
- onChange?: (nextValue: string) => void;
141
- onCancel?: (previousValue: string) => void;
142
- onSubmit?: (nextValue: string) => void;
143
- /** Aria label for the edit button. @default "Edit" */
144
- editLabel?: string;
145
- /** Font size for the heading. @default "3xl" */
146
- fontSize?: string;
147
- /** Max width constraint. @default "lg" */
148
- maxW?: string;
149
- }
150
- declare const EditableHeading: React__default.FC<EditableHeadingProps>;
151
-
152
138
  type DropzoneOptions = {
153
139
  noClick?: boolean;
154
140
  multiple?: boolean;
@@ -181,6 +167,28 @@ declare namespace FileField {
181
167
  var displayName: string;
182
168
  }
183
169
 
170
+ interface InlineEditProps {
171
+ value?: string;
172
+ onSubmit?: (nextValue: string) => void;
173
+ onChange?: (nextValue: string) => void;
174
+ onCancel?: (previousValue: string) => void;
175
+ /** @default "input" */
176
+ variant?: "input" | "textarea";
177
+ placeholder?: string;
178
+ /** @default "md" */
179
+ fontSize?: string;
180
+ fontWeight?: string;
181
+ maxW?: string;
182
+ disabled?: boolean;
183
+ /** When false, submitting an empty value reverts to the previous value. @default false */
184
+ allowEmpty?: boolean;
185
+ /** Number of rows used to calculate minH for textarea variant. @default 3 */
186
+ rows?: number;
187
+ /** Aria label for the edit button. @default "Edit" */
188
+ editLabel?: string;
189
+ }
190
+ declare const InlineEdit: React__default.FC<InlineEditProps>;
191
+
184
192
  interface InputFieldProps<T extends FieldValues> extends Omit<FormFieldProps<T>, "children"> {
185
193
  placeholder?: string;
186
194
  type?: InputProps["type"];
@@ -258,4 +266,4 @@ declare function TextareaField<T extends FieldValues>({ ref, ...props }: Textare
258
266
  ref?: React__default.Ref<HTMLTextAreaElement>;
259
267
  }): react_jsx_runtime.JSX.Element;
260
268
 
261
- export { ArrayField, type ArrayFieldProps, CheckboxField, type CheckboxFieldProps, CodeField, type CodeFieldProps, ColorPickerField, type ColorPickerFieldProps, ControlledFormField, type ControlledFormFieldProps, DatePickerField, type DatePickerFieldProps, DirtyFormGuard, type DirtyFormGuardProps, EditableHeading, type EditableHeadingProps, FileField, type FileFieldProps, FormField, type FormFieldProps, InputField, type InputFieldProps, MarkdownField, type MarkdownFieldProps, NumberInputField, type NumberInputFieldProps, RadioGroupField, type RadioGroupFieldProps, type RadioOption, SelectField, type SelectFieldProps, SwitchField, type SwitchFieldProps, TextareaField, type TextareaFieldProps };
269
+ export { ArrayField, type ArrayFieldProps, CheckboxField, type CheckboxFieldProps, CodeField, type CodeFieldProps, ColorPickerField, type ColorPickerFieldProps, ControlledFormField, type ControlledFormFieldProps, DatePickerField, type DatePickerFieldProps, DirtyFormGuard, type DirtyFormGuardProps, FileField, type FileFieldProps, FormField, type FormFieldProps, InlineEdit, type InlineEditProps, InputField, type InputFieldProps, MarkdownField, type MarkdownFieldProps, NumberInputField, type NumberInputFieldProps, RadioGroupField, type RadioGroupFieldProps, type RadioOption, SelectField, type SelectFieldProps, SwitchField, type SwitchFieldProps, TextareaField, type TextareaFieldProps };
@@ -1,10 +1,10 @@
1
- import { Popover, PopoverTrigger, PopoverContent, PopoverBody, LeavePageConfirmation, NumberInputRoot, NumberInputField, Radio, NativeSelect } from '../chunk-C4JI3JNA.js';
2
- import { Switch } from '../chunk-RJPEVNMJ.js';
3
- import { text_input_default } from '../chunk-PZCL4M6I.js';
4
- export { SearchInput } from '../chunk-PZCL4M6I.js';
5
- import { Stack, Grid, GridItem, Text, Input, IconButton, Box, ButtonGroup, Button, Field, HStack, Checkbox, Square, Editable, Flex, RadioGroup, Textarea, useEditableContext } from '@chakra-ui/react';
1
+ import { LeavePageConfirmation, NumberInputRoot, NumberInputField, Radio, NativeSelect } from '../chunk-6H4LQUMM.js';
2
+ import { Popover, PopoverTrigger, PopoverContent, PopoverBody, Switch } from '../chunk-WQIEF5N3.js';
3
+ export { SearchInput } from '../chunk-E7KRPPCQ.js';
4
+ import { text_input_default } from '../chunk-OU6H3KU4.js';
5
+ import { Stack, Grid, GridItem, Text, Input, IconButton, Box, ButtonGroup, Button, Field, HStack, Checkbox, Square, Flex, Editable, RadioGroup, Textarea, useEditableContext } from '@chakra-ui/react';
6
6
  import { Trash2, Plus, Upload, Pencil } from 'lucide-react';
7
- import React, { useId, useCallback, useEffect } from 'react';
7
+ import React, { useId, useCallback, useEffect, useRef } from 'react';
8
8
  import { useFormContext, useFieldArray, Controller } from 'react-hook-form';
9
9
  import { jsxs, jsx } from 'react/jsx-runtime';
10
10
  import { useBlocker } from 'react-router-dom';
@@ -449,46 +449,6 @@ var DirtyFormGuard = ({
449
449
  );
450
450
  };
451
451
  DirtyFormGuard.displayName = "DirtyFormGuard";
452
- var EditableControls = ({ editLabel }) => {
453
- const { editing } = useEditableContext();
454
- if (editing) return null;
455
- return /* @__PURE__ */ jsx(ButtonGroup, { children: /* @__PURE__ */ jsx(Editable.EditTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
456
- IconButton,
457
- {
458
- variant: "ghost",
459
- marginInlineStart: 2,
460
- "aria-label": editLabel,
461
- children: /* @__PURE__ */ jsx(Pencil, { size: 20 })
462
- }
463
- ) }) });
464
- };
465
- var EditableHeading = ({
466
- value,
467
- onChange,
468
- onCancel,
469
- onSubmit,
470
- editLabel = "Edit",
471
- fontSize = "3xl",
472
- maxW = "lg"
473
- }) => {
474
- return /* @__PURE__ */ jsxs(
475
- Editable.Root,
476
- {
477
- fontSize,
478
- maxW,
479
- value: String(value ?? ""),
480
- onValueChange: (details) => onChange?.(details.value),
481
- onValueRevert: (details) => onCancel?.(details.value),
482
- onValueCommit: (details) => onSubmit?.(details.value),
483
- children: [
484
- /* @__PURE__ */ jsx(Editable.Preview, {}),
485
- /* @__PURE__ */ jsx(Editable.Input, {}),
486
- /* @__PURE__ */ jsx(EditableControls, { editLabel })
487
- ]
488
- }
489
- );
490
- };
491
- EditableHeading.displayName = "EditableHeading";
492
452
  function FileField(props) {
493
453
  const {
494
454
  name,
@@ -629,6 +589,70 @@ var DropzoneContent = ({
629
589
  )
630
590
  ] });
631
591
  };
592
+ var CancelRefCapture = ({ cancelRef }) => {
593
+ const { cancel } = useEditableContext();
594
+ cancelRef.current = cancel;
595
+ return null;
596
+ };
597
+ var EditControls = ({ editLabel }) => {
598
+ const { editing } = useEditableContext();
599
+ if (editing) return null;
600
+ return /* @__PURE__ */ jsx(ButtonGroup, { children: /* @__PURE__ */ jsx(Editable.EditTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
601
+ IconButton,
602
+ {
603
+ variant: "ghost",
604
+ marginInlineStart: 2,
605
+ "aria-label": editLabel,
606
+ children: /* @__PURE__ */ jsx(Pencil, { size: 16 })
607
+ }
608
+ ) }) });
609
+ };
610
+ var InlineEdit = ({
611
+ value,
612
+ onSubmit,
613
+ onChange,
614
+ onCancel,
615
+ variant = "input",
616
+ placeholder,
617
+ fontSize = "md",
618
+ fontWeight,
619
+ maxW,
620
+ disabled,
621
+ allowEmpty = false,
622
+ rows = 3,
623
+ editLabel = "Edit"
624
+ }) => {
625
+ const cancelRef = useRef(null);
626
+ const handleSubmit = (details) => {
627
+ const trimmed = details.value.trim();
628
+ if (!allowEmpty && trimmed === "") {
629
+ cancelRef.current?.();
630
+ return;
631
+ }
632
+ onSubmit?.(trimmed);
633
+ };
634
+ return /* @__PURE__ */ jsxs(
635
+ Editable.Root,
636
+ {
637
+ fontSize,
638
+ fontWeight,
639
+ maxW,
640
+ value: String(value ?? ""),
641
+ onValueChange: (d) => onChange?.(d.value),
642
+ onValueRevert: (d) => onCancel?.(d.value),
643
+ onValueCommit: handleSubmit,
644
+ disabled,
645
+ placeholder,
646
+ children: [
647
+ /* @__PURE__ */ jsx(CancelRefCapture, { cancelRef }),
648
+ /* @__PURE__ */ jsx(Editable.Preview, {}),
649
+ variant === "textarea" ? /* @__PURE__ */ jsx(Editable.Textarea, { minH: `${rows * 1.5}em` }) : /* @__PURE__ */ jsx(Editable.Input, {}),
650
+ /* @__PURE__ */ jsx(EditControls, { editLabel })
651
+ ]
652
+ }
653
+ );
654
+ };
655
+ InlineEdit.displayName = "InlineEdit";
632
656
  function InputField({
633
657
  ref,
634
658
  ...props
@@ -904,6 +928,6 @@ function TextareaField({
904
928
  }
905
929
  TextareaField.displayName = "TextareaField";
906
930
 
907
- export { ArrayField, CheckboxField, CodeField, ColorPickerField, ControlledFormField, DatePickerField, DirtyFormGuard, EditableHeading, FileField, FormField, InputField, MarkdownField, NumberInputField2 as NumberInputField, RadioGroupField, SelectField, SwitchField, TextareaField };
931
+ export { ArrayField, CheckboxField, CodeField, ColorPickerField, ControlledFormField, DatePickerField, DirtyFormGuard, FileField, FormField, InlineEdit, InputField, MarkdownField, NumberInputField2 as NumberInputField, RadioGroupField, SelectField, SwitchField, TextareaField };
908
932
  //# sourceMappingURL=index.js.map
909
933
  //# sourceMappingURL=index.js.map