@smwb/ui-react 2.5.0 → 2.6.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.
- package/dist/assets/styles/less/components/confirmDialog/confirmDialog.entry.css +1 -0
- package/dist/assets/styles/less/components/fileDrop/fileDrop.entry.css +1 -0
- package/dist/assets/styles/less/components/fileInput/fileInput.entry.css +1 -0
- package/dist/assets/styles/less/components/floatingWindow/floatingWindow.entry.css +1 -0
- package/dist/components/dataDisplay/chat/chat.d.ts +1 -1
- package/dist/components/dataDisplay/chat/chat.js.map +1 -1
- package/dist/components/dataDisplay/chat/useChatFileUpload.d.ts +16 -4
- package/dist/components/dataDisplay/chat/useChatFileUpload.js +38 -29
- package/dist/components/dataDisplay/chat/useChatFileUpload.js.map +1 -1
- package/dist/components/feedBack/confirmDialog/confirmDialog.d.ts +27 -0
- package/dist/components/feedBack/confirmDialog/confirmDialog.js +49 -0
- package/dist/components/feedBack/confirmDialog/confirmDialog.js.map +1 -0
- package/dist/components/feedBack/confirmDialog/index.d.ts +2 -0
- package/dist/components/inputs/fileDrop/countPreview.js +15 -0
- package/dist/components/inputs/fileDrop/countPreview.js.map +1 -0
- package/dist/components/inputs/fileDrop/fileDrop.d.ts +1 -1
- package/dist/components/inputs/fileDrop/fileDrop.js +60 -0
- package/dist/components/inputs/fileDrop/fileDrop.js.map +1 -0
- package/dist/components/inputs/fileDrop/index.d.ts +9 -0
- package/dist/components/inputs/fileDrop/preview.js +41 -0
- package/dist/components/inputs/fileDrop/preview.js.map +1 -0
- package/dist/components/inputs/fileDrop/previewWrapper.js +27 -0
- package/dist/components/inputs/fileDrop/previewWrapper.js.map +1 -0
- package/dist/components/inputs/fileDrop/utils.js +7 -0
- package/dist/components/inputs/fileDrop/utils.js.map +1 -0
- package/dist/components/inputs/fileInput/fileInput.d.ts +1 -1
- package/dist/components/inputs/fileInput/fileInput.js +35 -0
- package/dist/components/inputs/fileInput/fileInput.js.map +1 -0
- package/dist/components/inputs/fileInput/index.d.ts +2 -0
- package/dist/components/layout/floatingWindow/floatingWindow.d.ts +92 -0
- package/dist/components/layout/floatingWindow/floatingWindow.js +311 -0
- package/dist/components/layout/floatingWindow/floatingWindow.js.map +1 -0
- package/dist/components/layout/floatingWindow/index.d.ts +2 -0
- package/dist/headless/components/dataDisplay/chat/chat.js.map +1 -1
- package/dist/headless/components/dataDisplay/chat/useChatFileUpload.js +38 -29
- package/dist/headless/components/dataDisplay/chat/useChatFileUpload.js.map +1 -1
- package/dist/headless/components/feedBack/confirmDialog/confirmDialog.js +48 -0
- package/dist/headless/components/feedBack/confirmDialog/confirmDialog.js.map +1 -0
- package/dist/headless/components/inputs/fileDrop/countPreview.js +15 -0
- package/dist/headless/components/inputs/fileDrop/countPreview.js.map +1 -0
- package/dist/headless/components/inputs/fileDrop/fileDrop.js +59 -0
- package/dist/headless/components/inputs/fileDrop/fileDrop.js.map +1 -0
- package/dist/headless/components/inputs/fileDrop/preview.js +41 -0
- package/dist/headless/components/inputs/fileDrop/preview.js.map +1 -0
- package/dist/headless/components/inputs/fileDrop/previewWrapper.js +27 -0
- package/dist/headless/components/inputs/fileDrop/previewWrapper.js.map +1 -0
- package/dist/headless/components/inputs/fileDrop/utils.js +7 -0
- package/dist/headless/components/inputs/fileDrop/utils.js.map +1 -0
- package/dist/headless/components/inputs/fileInput/fileInput.js +34 -0
- package/dist/headless/components/inputs/fileInput/fileInput.js.map +1 -0
- package/dist/headless/components/layout/floatingWindow/floatingWindow.js +310 -0
- package/dist/headless/components/layout/floatingWindow/floatingWindow.js.map +1 -0
- package/dist/headless/hooks/useDropzone.js +47 -0
- package/dist/headless/hooks/useDropzone.js.map +1 -0
- package/dist/headless/index.js +277 -259
- package/dist/headless/index.js.map +1 -1
- package/dist/hooks/useDropzone.d.ts +44 -0
- package/dist/hooks/useDropzone.js +47 -0
- package/dist/hooks/useDropzone.js.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +277 -259
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-confirm-dialog__body{display:flex;flex-direction:column;gap:8px;min-width:280px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-file-drop{background-color:var(--smui-toggleTrackColor);width:326px;height:200px}.smwb-file-drop__input{display:flex;justify-content:center;align-items:center;flex-wrap:wrap;height:100%;width:100%;border:3px dashed purple}.smwb-file-drop__input-text{text-align:center}.smwb-file-drop__preview{position:relative;height:100%;width:100%}.smwb-file-drop__preview-button{position:absolute;top:-18px;right:-18px;z-index:1}.smwb-file-drop__preview-gallery{height:100%;overflow:auto;border:3px solid purple;border-radius:4px}.smwb-file-drop__preview-gallery-image{width:100%;height:100%}.smwb-file-drop__preview-gallery-file{width:calc(100% - 4px);height:calc(100% - 4px);display:flex;align-items:center;justify-content:center;border:1px solid purple;user-select:none;margin:2px}.smwb-file-drop__preview-count{display:flex;align-items:center;justify-content:center;padding:1px 4px;height:100%;width:100%;overflow:auto;border:3px solid purple;border-radius:4px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.file-input{width:100px;height:30px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.smwb-floating-window{background-color:var(--smui-surfaceBackground);color:var(--smui-onSurfaceColor);position:fixed;z-index:150;display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden;border-radius:12px;box-shadow:#00000024 0 8px 10px -5px,#00000024 0 1px 14px 1px,#00000024 0 6px 22px 4px;opacity:0;transition:opacity .12s ease-in-out}.smwb-floating-window.smwb-floating-window_entered{opacity:1}.smwb-floating-window__header{display:flex;align-items:center;gap:4px;flex-shrink:0;height:36px;padding:0 12px;border-bottom:1px solid var(--smui-dividerColor);touch-action:none;user-select:none;cursor:move}.smwb-floating-window__header:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:-2px}.smwb-floating-window__grip{display:inline-flex;align-items:center;color:var(--smui-onSurfaceVariant);flex-shrink:0;cursor:move}.smwb-floating-window__grip:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:2px;border-radius:2px}.smwb-floating-window__title{font-family:var(--smui-fontFamily);font-size:14px;font-weight:500;line-height:1.5;color:var(--smui-onSurfaceColor);flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.smwb-floating-window__actions{display:flex;align-items:center;gap:2px;flex-shrink:0;margin-left:auto;cursor:default}.smwb-floating-window__action{display:inline-flex;align-items:center;justify-content:center;padding:2px;border:none;border-radius:4px;background:transparent;color:var(--smui-onSurfaceVariant);cursor:pointer}.smwb-floating-window__action:hover{background-color:var(--smui-onSurfaceHover);color:var(--smui-onSurfaceColor)}.smwb-floating-window__action:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:-2px}.smwb-floating-window__body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:auto;padding:12px}.smwb-floating-window.smwb-collapsed{height:auto}.smwb-floating-window__resize{position:absolute;touch-action:none;user-select:none;z-index:1}.smwb-floating-window__resize:focus-visible{outline:2px solid var(--smui-primaryColor);outline-offset:-2px}.smwb-floating-window__resize_n,.smwb-floating-window__resize_s{left:6px;right:6px;height:6px;cursor:ns-resize}.smwb-floating-window__resize_e,.smwb-floating-window__resize_w{top:6px;bottom:6px;width:6px;cursor:ew-resize}.smwb-floating-window__resize_n{top:0}.smwb-floating-window__resize_s{bottom:0}.smwb-floating-window__resize_e{right:0}.smwb-floating-window__resize_w{left:0}.smwb-floating-window__resize_ne,.smwb-floating-window__resize_nw,.smwb-floating-window__resize_se,.smwb-floating-window__resize_sw{width:12px;height:12px}.smwb-floating-window__resize_ne{top:0;right:0;cursor:nesw-resize}.smwb-floating-window__resize_nw{top:0;left:0;cursor:nwse-resize}.smwb-floating-window__resize_se{bottom:0;right:0;cursor:nwse-resize}.smwb-floating-window__resize_sw{bottom:0;left:0;cursor:nesw-resize}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PropsWithChildren, ReactNode } from "react";
|
|
2
|
-
import type { Accept } from "
|
|
2
|
+
import type { Accept } from "./useChatFileUpload";
|
|
3
3
|
import { ChatMessagesProps } from "./chatMessages";
|
|
4
4
|
import { ChatAnchor, ChatLayoutMode, ChatMessage, ChatMessageRenderContext, ChatThemeMode } from "./types";
|
|
5
5
|
export interface ChatProps extends PropsWithChildren, Omit<ChatMessageRenderContext, "showAvatars" | "showAttachments"> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sources":["../../../../src/components/dataDisplay/chat/chat.tsx"],"sourcesContent":["import React, { PropsWithChildren, ReactNode, useId, useMemo } from \"react\";\nimport cn from \"clsx\";\nimport type { Accept } from \"react-dropzone\";\nimport { FloatingButton } from \"../../inputs/floatingButton/floatingButton\";\nimport Icon from \"../../base/icon/icon\";\nimport { useControllableState } from \"../../../hooks/useControllableState\";\nimport ChatComposer from \"./chatComposer\";\nimport ChatHeader from \"./chatHeader\";\nimport ChatMessages, { ChatMessagesProps } from \"./chatMessages\";\nimport ChatShell from \"./chatShell\";\nimport useChatFileUpload from \"./useChatFileUpload\";\nimport {\n ChatAnchor,\n ChatLayoutMode,\n ChatMessage,\n ChatMessageRenderContext,\n ChatThemeMode,\n CHAT_EXPAND_LAYOUTS,\n} from \"./types\";\nimport { pickInitialLayout, resolveAllowedLayouts, shouldShowChatCloseButton } from \"./utils\";\n\nexport interface ChatProps\n extends PropsWithChildren, Omit<ChatMessageRenderContext, \"showAvatars\" | \"showAttachments\"> {\n className?: string;\n messages: ChatMessage[];\n showAvatars?: boolean;\n showAttachments?: boolean;\n headerTitle?: ReactNode;\n headerSubtitle?: ReactNode;\n headerActions?: ReactNode;\n footer?: ReactNode;\n anchor?: ChatAnchor;\n themeMode?: ChatThemeMode;\n allowedLayouts?: ChatLayoutMode[];\n layout?: ChatLayoutMode;\n defaultLayout?: ChatLayoutMode;\n onLayoutChange?: (layout: ChatLayoutMode) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n floatingTrigger?: boolean;\n triggerIcon?: ReactNode;\n triggerLabel?: string;\n onLoadMore?: () => void | Promise<void>;\n hasMore?: boolean;\n onSendMessage?: (text: string) => void | Promise<void>;\n composerPlaceholder?: string;\n composerDisabled?: boolean;\n composerShiftEnterNewline?: boolean;\n composerCtrlEnterNewline?: boolean;\n fileUpload?: boolean;\n onUploadFiles?: (files: File[]) => void | Promise<void>;\n fileUploadAccept?: Accept;\n fileUploadMaxFiles?: number;\n attachAriaLabel?: string;\n loading?: boolean;\n loadingMore?: boolean;\n loadingSkeletonCount?: number;\n renderMessage?: ChatMessagesProps[\"renderMessage\"];\n embedded?: boolean;\n overlayContext?: boolean;\n showStatus?: boolean;\n statusIcons?: ChatMessageRenderContext[\"statusIcons\"];\n renderStatus?: ChatMessageRenderContext[\"renderStatus\"];\n showCloseButton?: boolean;\n}\n\nexport function Chat({\n className,\n messages,\n showAvatars = false,\n showAttachments = false,\n headerTitle,\n headerSubtitle,\n headerActions,\n footer,\n children,\n anchor = \"bottom-right\",\n themeMode = \"inherit\",\n allowedLayouts: allowedLayoutsProp,\n layout: layoutProp,\n defaultLayout,\n onLayoutChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n floatingTrigger = false,\n triggerIcon,\n triggerLabel,\n onLoadMore,\n hasMore,\n onSendMessage,\n composerPlaceholder = \"message\",\n composerDisabled,\n composerShiftEnterNewline = true,\n composerCtrlEnterNewline = true,\n fileUpload = false,\n onUploadFiles,\n fileUploadAccept,\n fileUploadMaxFiles,\n attachAriaLabel,\n loading,\n loadingMore,\n loadingSkeletonCount,\n renderMessage,\n embedded = false,\n overlayContext = false,\n showStatus = false,\n statusIcons,\n renderStatus,\n showCloseButton,\n}: ChatProps) {\n const allowedLayouts = useMemo(\n () => resolveAllowedLayouts(allowedLayoutsProp ?? CHAT_EXPAND_LAYOUTS),\n [allowedLayoutsProp]\n );\n\n const [open, setOpen] = useControllableState<boolean>({\n value: openProp,\n defaultValue: defaultOpen,\n onChange: onOpenChange,\n });\n\n const [layout, setLayout] = useControllableState<ChatLayoutMode>({\n value: layoutProp,\n defaultValue: pickInitialLayout(allowedLayouts, defaultLayout),\n onChange: onLayoutChange,\n });\n\n const effectiveLayout: ChatLayoutMode = embedded\n ? \"fullHeight\"\n : floatingTrigger\n ? open\n ? layout\n : \"closed\"\n : layout;\n\n const handleOpen = () => {\n setOpen(true);\n if (layout === \"closed\") {\n setLayout(pickInitialLayout(allowedLayouts, defaultLayout));\n }\n };\n\n const handleClose = () => {\n setOpen(false);\n };\n\n const handleLayoutChange = (next: ChatLayoutMode) => {\n setOpen(true);\n setLayout(next);\n };\n\n const {\n enabled: fileUploadEnabled,\n getRootProps,\n getInputProps,\n isDragActive,\n } = useChatFileUpload({\n enabled: fileUpload,\n accept: fileUploadAccept,\n maxFiles: fileUploadMaxFiles,\n onUploadFiles,\n disabled: composerDisabled,\n });\n\n const attachInputId = useId();\n\n const showComposer = Boolean(onSendMessage) || fileUploadEnabled;\n\n const fileInput = fileUploadEnabled ? (\n <input {...getInputProps({ id: attachInputId })} data-testid=\"chat-file-input\" />\n ) : null;\n\n const resolvedFooter =\n footer ??\n children ??\n (showComposer ? (\n <>\n {fileInput}\n <ChatComposer\n onSendMessage={onSendMessage}\n placeholder={composerPlaceholder}\n disabled={composerDisabled}\n shiftEnterNewline={composerShiftEnterNewline}\n ctrlEnterNewline={composerCtrlEnterNewline}\n fileUpload={fileUploadEnabled}\n attachInputId={fileUploadEnabled ? attachInputId : undefined}\n attachAriaLabel={attachAriaLabel}\n />\n </>\n ) : undefined);\n\n const chatMessages = (\n <ChatMessages\n messages={messages}\n showAvatars={showAvatars}\n showAttachments={showAttachments}\n showStatus={showStatus}\n statusIcons={statusIcons}\n renderStatus={renderStatus}\n onLoadMore={onLoadMore}\n hasMore={hasMore}\n loading={loading}\n loadingMore={loadingMore}\n loadingSkeletonCount={loadingSkeletonCount}\n renderMessage={renderMessage}\n />\n );\n\n const chatBody = chatMessages;\n\n const fileDropzoneRootProps = fileUploadEnabled ? getRootProps() : undefined;\n\n const closeButtonVisible = shouldShowChatCloseButton({\n floatingTrigger,\n embedded,\n overlayContext,\n effectiveLayout,\n showCloseButton,\n });\n\n return (\n <div\n className={cn(\n \"smwb-chat\",\n !embedded && `smwb-chat_${anchor}`,\n embedded && \"smwb-chat_embedded\",\n overlayContext && \"smwb-chat_overlay-context\",\n className\n )}\n data-testid=\"chat\"\n >\n {floatingTrigger && !embedded && !open ? (\n <FloatingButton\n className=\"smwb-chat__trigger\"\n aria-label={triggerLabel ?? \"Open chat\"}\n data-testid=\"chat-trigger\"\n onClick={handleOpen}\n >\n {triggerIcon ?? <Icon name=\"chat\" size={24} />}\n </FloatingButton>\n ) : null}\n <ChatShell\n layout={effectiveLayout}\n anchor={anchor}\n themeMode={themeMode}\n embedded={embedded}\n overlayContext={overlayContext}\n fileDropzoneRootProps={fileDropzoneRootProps}\n fileDropzoneActive={fileUploadEnabled && isDragActive}\n header={\n <ChatHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n layout={effectiveLayout === \"closed\" ? layout : effectiveLayout}\n allowedLayouts={allowedLayouts}\n onLayoutChange={handleLayoutChange}\n onClose={closeButtonVisible ? handleClose : undefined}\n />\n }\n footer={resolvedFooter}\n >\n {chatBody}\n </ChatShell>\n </div>\n );\n}\n\nexport default Chat;\n"],"names":["Chat","className","messages","showAvatars","showAttachments","headerTitle","headerSubtitle","headerActions","footer","children","anchor","themeMode","allowedLayoutsProp","layoutProp","defaultLayout","onLayoutChange","openProp","defaultOpen","onOpenChange","floatingTrigger","triggerIcon","triggerLabel","onLoadMore","hasMore","onSendMessage","composerPlaceholder","composerDisabled","composerShiftEnterNewline","composerCtrlEnterNewline","fileUpload","onUploadFiles","fileUploadAccept","fileUploadMaxFiles","attachAriaLabel","loading","loadingMore","loadingSkeletonCount","renderMessage","embedded","overlayContext","showStatus","statusIcons","renderStatus","showCloseButton","allowedLayouts","useMemo","resolveAllowedLayouts","CHAT_EXPAND_LAYOUTS","open","setOpen","useControllableState","layout","setLayout","pickInitialLayout","effectiveLayout","handleOpen","handleClose","handleLayoutChange","next","fileUploadEnabled","getRootProps","getInputProps","isDragActive","useChatFileUpload","attachInputId","useId","showComposer","fileInput","jsx","resolvedFooter","_a","jsxs","Fragment","ChatComposer","chatBody","ChatMessages","fileDropzoneRootProps","closeButtonVisible","shouldShowChatCloseButton","cn","FloatingButton","Icon","ChatShell","ChatHeader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat.js","sources":["../../../../src/components/dataDisplay/chat/chat.tsx"],"sourcesContent":["import React, { PropsWithChildren, ReactNode, useId, useMemo } from \"react\";\nimport cn from \"clsx\";\nimport type { Accept } from \"./useChatFileUpload\";\nimport { FloatingButton } from \"../../inputs/floatingButton/floatingButton\";\nimport Icon from \"../../base/icon/icon\";\nimport { useControllableState } from \"../../../hooks/useControllableState\";\nimport ChatComposer from \"./chatComposer\";\nimport ChatHeader from \"./chatHeader\";\nimport ChatMessages, { ChatMessagesProps } from \"./chatMessages\";\nimport ChatShell from \"./chatShell\";\nimport useChatFileUpload from \"./useChatFileUpload\";\nimport {\n ChatAnchor,\n ChatLayoutMode,\n ChatMessage,\n ChatMessageRenderContext,\n ChatThemeMode,\n CHAT_EXPAND_LAYOUTS,\n} from \"./types\";\nimport { pickInitialLayout, resolveAllowedLayouts, shouldShowChatCloseButton } from \"./utils\";\n\nexport interface ChatProps\n extends PropsWithChildren, Omit<ChatMessageRenderContext, \"showAvatars\" | \"showAttachments\"> {\n className?: string;\n messages: ChatMessage[];\n showAvatars?: boolean;\n showAttachments?: boolean;\n headerTitle?: ReactNode;\n headerSubtitle?: ReactNode;\n headerActions?: ReactNode;\n footer?: ReactNode;\n anchor?: ChatAnchor;\n themeMode?: ChatThemeMode;\n allowedLayouts?: ChatLayoutMode[];\n layout?: ChatLayoutMode;\n defaultLayout?: ChatLayoutMode;\n onLayoutChange?: (layout: ChatLayoutMode) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n floatingTrigger?: boolean;\n triggerIcon?: ReactNode;\n triggerLabel?: string;\n onLoadMore?: () => void | Promise<void>;\n hasMore?: boolean;\n onSendMessage?: (text: string) => void | Promise<void>;\n composerPlaceholder?: string;\n composerDisabled?: boolean;\n composerShiftEnterNewline?: boolean;\n composerCtrlEnterNewline?: boolean;\n fileUpload?: boolean;\n onUploadFiles?: (files: File[]) => void | Promise<void>;\n fileUploadAccept?: Accept;\n fileUploadMaxFiles?: number;\n attachAriaLabel?: string;\n loading?: boolean;\n loadingMore?: boolean;\n loadingSkeletonCount?: number;\n renderMessage?: ChatMessagesProps[\"renderMessage\"];\n embedded?: boolean;\n overlayContext?: boolean;\n showStatus?: boolean;\n statusIcons?: ChatMessageRenderContext[\"statusIcons\"];\n renderStatus?: ChatMessageRenderContext[\"renderStatus\"];\n showCloseButton?: boolean;\n}\n\nexport function Chat({\n className,\n messages,\n showAvatars = false,\n showAttachments = false,\n headerTitle,\n headerSubtitle,\n headerActions,\n footer,\n children,\n anchor = \"bottom-right\",\n themeMode = \"inherit\",\n allowedLayouts: allowedLayoutsProp,\n layout: layoutProp,\n defaultLayout,\n onLayoutChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n floatingTrigger = false,\n triggerIcon,\n triggerLabel,\n onLoadMore,\n hasMore,\n onSendMessage,\n composerPlaceholder = \"message\",\n composerDisabled,\n composerShiftEnterNewline = true,\n composerCtrlEnterNewline = true,\n fileUpload = false,\n onUploadFiles,\n fileUploadAccept,\n fileUploadMaxFiles,\n attachAriaLabel,\n loading,\n loadingMore,\n loadingSkeletonCount,\n renderMessage,\n embedded = false,\n overlayContext = false,\n showStatus = false,\n statusIcons,\n renderStatus,\n showCloseButton,\n}: ChatProps) {\n const allowedLayouts = useMemo(\n () => resolveAllowedLayouts(allowedLayoutsProp ?? CHAT_EXPAND_LAYOUTS),\n [allowedLayoutsProp]\n );\n\n const [open, setOpen] = useControllableState<boolean>({\n value: openProp,\n defaultValue: defaultOpen,\n onChange: onOpenChange,\n });\n\n const [layout, setLayout] = useControllableState<ChatLayoutMode>({\n value: layoutProp,\n defaultValue: pickInitialLayout(allowedLayouts, defaultLayout),\n onChange: onLayoutChange,\n });\n\n const effectiveLayout: ChatLayoutMode = embedded\n ? \"fullHeight\"\n : floatingTrigger\n ? open\n ? layout\n : \"closed\"\n : layout;\n\n const handleOpen = () => {\n setOpen(true);\n if (layout === \"closed\") {\n setLayout(pickInitialLayout(allowedLayouts, defaultLayout));\n }\n };\n\n const handleClose = () => {\n setOpen(false);\n };\n\n const handleLayoutChange = (next: ChatLayoutMode) => {\n setOpen(true);\n setLayout(next);\n };\n\n const {\n enabled: fileUploadEnabled,\n getRootProps,\n getInputProps,\n isDragActive,\n } = useChatFileUpload({\n enabled: fileUpload,\n accept: fileUploadAccept,\n maxFiles: fileUploadMaxFiles,\n onUploadFiles,\n disabled: composerDisabled,\n });\n\n const attachInputId = useId();\n\n const showComposer = Boolean(onSendMessage) || fileUploadEnabled;\n\n const fileInput = fileUploadEnabled ? (\n <input {...getInputProps({ id: attachInputId })} data-testid=\"chat-file-input\" />\n ) : null;\n\n const resolvedFooter =\n footer ??\n children ??\n (showComposer ? (\n <>\n {fileInput}\n <ChatComposer\n onSendMessage={onSendMessage}\n placeholder={composerPlaceholder}\n disabled={composerDisabled}\n shiftEnterNewline={composerShiftEnterNewline}\n ctrlEnterNewline={composerCtrlEnterNewline}\n fileUpload={fileUploadEnabled}\n attachInputId={fileUploadEnabled ? attachInputId : undefined}\n attachAriaLabel={attachAriaLabel}\n />\n </>\n ) : undefined);\n\n const chatMessages = (\n <ChatMessages\n messages={messages}\n showAvatars={showAvatars}\n showAttachments={showAttachments}\n showStatus={showStatus}\n statusIcons={statusIcons}\n renderStatus={renderStatus}\n onLoadMore={onLoadMore}\n hasMore={hasMore}\n loading={loading}\n loadingMore={loadingMore}\n loadingSkeletonCount={loadingSkeletonCount}\n renderMessage={renderMessage}\n />\n );\n\n const chatBody = chatMessages;\n\n const fileDropzoneRootProps = fileUploadEnabled ? getRootProps() : undefined;\n\n const closeButtonVisible = shouldShowChatCloseButton({\n floatingTrigger,\n embedded,\n overlayContext,\n effectiveLayout,\n showCloseButton,\n });\n\n return (\n <div\n className={cn(\n \"smwb-chat\",\n !embedded && `smwb-chat_${anchor}`,\n embedded && \"smwb-chat_embedded\",\n overlayContext && \"smwb-chat_overlay-context\",\n className\n )}\n data-testid=\"chat\"\n >\n {floatingTrigger && !embedded && !open ? (\n <FloatingButton\n className=\"smwb-chat__trigger\"\n aria-label={triggerLabel ?? \"Open chat\"}\n data-testid=\"chat-trigger\"\n onClick={handleOpen}\n >\n {triggerIcon ?? <Icon name=\"chat\" size={24} />}\n </FloatingButton>\n ) : null}\n <ChatShell\n layout={effectiveLayout}\n anchor={anchor}\n themeMode={themeMode}\n embedded={embedded}\n overlayContext={overlayContext}\n fileDropzoneRootProps={fileDropzoneRootProps}\n fileDropzoneActive={fileUploadEnabled && isDragActive}\n header={\n <ChatHeader\n title={headerTitle}\n subtitle={headerSubtitle}\n actions={headerActions}\n layout={effectiveLayout === \"closed\" ? layout : effectiveLayout}\n allowedLayouts={allowedLayouts}\n onLayoutChange={handleLayoutChange}\n onClose={closeButtonVisible ? handleClose : undefined}\n />\n }\n footer={resolvedFooter}\n >\n {chatBody}\n </ChatShell>\n </div>\n );\n}\n\nexport default Chat;\n"],"names":["Chat","className","messages","showAvatars","showAttachments","headerTitle","headerSubtitle","headerActions","footer","children","anchor","themeMode","allowedLayoutsProp","layoutProp","defaultLayout","onLayoutChange","openProp","defaultOpen","onOpenChange","floatingTrigger","triggerIcon","triggerLabel","onLoadMore","hasMore","onSendMessage","composerPlaceholder","composerDisabled","composerShiftEnterNewline","composerCtrlEnterNewline","fileUpload","onUploadFiles","fileUploadAccept","fileUploadMaxFiles","attachAriaLabel","loading","loadingMore","loadingSkeletonCount","renderMessage","embedded","overlayContext","showStatus","statusIcons","renderStatus","showCloseButton","allowedLayouts","useMemo","resolveAllowedLayouts","CHAT_EXPAND_LAYOUTS","open","setOpen","useControllableState","layout","setLayout","pickInitialLayout","effectiveLayout","handleOpen","handleClose","handleLayoutChange","next","fileUploadEnabled","getRootProps","getInputProps","isDragActive","useChatFileUpload","attachInputId","useId","showComposer","fileInput","jsx","resolvedFooter","_a","jsxs","Fragment","ChatComposer","chatBody","ChatMessages","fileDropzoneRootProps","closeButtonVisible","shouldShowChatCloseButton","cn","FloatingButton","Icon","ChatShell","ChatHeader"],"mappings":"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"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type DropzoneAccept, type DropzoneInputProps } from "../../../hooks/useDropzone";
|
|
3
|
+
/** Kept as a named alias so `ChatProps.fileUploadAccept` reads the same as before. */
|
|
4
|
+
export type Accept = DropzoneAccept;
|
|
2
5
|
export interface UseChatFileUploadOptions {
|
|
3
6
|
enabled?: boolean;
|
|
4
7
|
accept?: Accept;
|
|
@@ -6,14 +9,23 @@ export interface UseChatFileUploadOptions {
|
|
|
6
9
|
onUploadFiles?: (files: File[]) => void | Promise<void>;
|
|
7
10
|
disabled?: boolean;
|
|
8
11
|
}
|
|
12
|
+
export interface ChatFileUploadRootProps {
|
|
13
|
+
onDragOver: (event: React.DragEvent<HTMLElement>) => void;
|
|
14
|
+
onDragLeave: () => void;
|
|
15
|
+
onDrop: (event: React.DragEvent<HTMLElement>) => void;
|
|
16
|
+
}
|
|
9
17
|
export declare function resolveChatFileUploadMaxFiles(maxFiles?: number): number;
|
|
10
18
|
export declare function useChatFileUpload({ enabled, accept, maxFiles, onUploadFiles, disabled, }: UseChatFileUploadOptions): {
|
|
11
19
|
enabled: boolean;
|
|
12
20
|
maxFiles: number;
|
|
13
|
-
getRootProps:
|
|
14
|
-
getInputProps:
|
|
21
|
+
getRootProps: () => ChatFileUploadRootProps;
|
|
22
|
+
getInputProps: (extra?: {
|
|
23
|
+
id?: string;
|
|
24
|
+
}) => DropzoneInputProps & {
|
|
25
|
+
id?: string;
|
|
26
|
+
};
|
|
15
27
|
open: () => void;
|
|
16
|
-
inputRef:
|
|
28
|
+
inputRef: React.RefObject<HTMLInputElement>;
|
|
17
29
|
isDragActive: boolean;
|
|
18
30
|
};
|
|
19
31
|
export default useChatFileUpload;
|
|
@@ -1,42 +1,51 @@
|
|
|
1
|
-
import { useDropzone as
|
|
2
|
-
import { CHAT_DEFAULT_FILE_UPLOAD_MAX_FILES as
|
|
3
|
-
function
|
|
4
|
-
return e == null ?
|
|
1
|
+
import { useDropzone as g } from "../../../hooks/useDropzone.js";
|
|
2
|
+
import { CHAT_DEFAULT_FILE_UPLOAD_MAX_FILES as F } from "./types.js";
|
|
3
|
+
function d(e) {
|
|
4
|
+
return e == null ? F : Math.max(1, e);
|
|
5
5
|
}
|
|
6
|
-
function
|
|
6
|
+
function v({
|
|
7
7
|
enabled: e = !1,
|
|
8
|
-
accept:
|
|
9
|
-
maxFiles:
|
|
10
|
-
onUploadFiles:
|
|
11
|
-
disabled:
|
|
8
|
+
accept: p,
|
|
9
|
+
maxFiles: s,
|
|
10
|
+
onUploadFiles: t,
|
|
11
|
+
disabled: i = !1
|
|
12
12
|
}) {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
const n = d(s), r = e && !!t && !i, {
|
|
14
|
+
getRootProps: l,
|
|
15
|
+
getInputProps: c,
|
|
16
|
+
open: u,
|
|
17
|
+
isDragActive: a,
|
|
18
|
+
inputRef: P
|
|
19
|
+
} = g({
|
|
20
|
+
accept: p,
|
|
21
|
+
maxFiles: n,
|
|
22
|
+
multiple: n > 1,
|
|
23
|
+
disabled: !r,
|
|
24
|
+
onDropAccepted: (o) => {
|
|
25
|
+
t && t(o);
|
|
23
26
|
}
|
|
24
27
|
});
|
|
25
28
|
return {
|
|
26
|
-
enabled:
|
|
27
|
-
maxFiles:
|
|
28
|
-
getRootProps:
|
|
29
|
-
|
|
29
|
+
enabled: r,
|
|
30
|
+
maxFiles: n,
|
|
31
|
+
getRootProps: () => {
|
|
32
|
+
const { onClick: o, ...f } = l();
|
|
33
|
+
return f;
|
|
34
|
+
},
|
|
35
|
+
getInputProps: (o) => ({
|
|
36
|
+
...c(),
|
|
37
|
+
...o != null ? o : {}
|
|
38
|
+
}),
|
|
30
39
|
open: () => {
|
|
31
|
-
|
|
40
|
+
u();
|
|
32
41
|
},
|
|
33
|
-
inputRef:
|
|
34
|
-
isDragActive:
|
|
42
|
+
inputRef: P,
|
|
43
|
+
isDragActive: a
|
|
35
44
|
};
|
|
36
45
|
}
|
|
37
46
|
export {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
v as default,
|
|
48
|
+
d as resolveChatFileUploadMaxFiles,
|
|
49
|
+
v as useChatFileUpload
|
|
41
50
|
};
|
|
42
51
|
//# sourceMappingURL=useChatFileUpload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatFileUpload.js","sources":["../../../../src/components/dataDisplay/chat/useChatFileUpload.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"useChatFileUpload.js","sources":["../../../../src/components/dataDisplay/chat/useChatFileUpload.ts"],"sourcesContent":["import React from \"react\";\nimport { type DropzoneAccept, type DropzoneInputProps, useDropzone } from \"../../../hooks/useDropzone\";\nimport { CHAT_DEFAULT_FILE_UPLOAD_MAX_FILES } from \"./types\";\n\n/** Kept as a named alias so `ChatProps.fileUploadAccept` reads the same as before. */\nexport type Accept = DropzoneAccept;\n\nexport interface UseChatFileUploadOptions {\n enabled?: boolean;\n accept?: Accept;\n maxFiles?: number;\n onUploadFiles?: (files: File[]) => void | Promise<void>;\n disabled?: boolean;\n}\n\nexport interface ChatFileUploadRootProps {\n onDragOver: (event: React.DragEvent<HTMLElement>) => void;\n onDragLeave: () => void;\n onDrop: (event: React.DragEvent<HTMLElement>) => void;\n}\n\nexport function resolveChatFileUploadMaxFiles(maxFiles?: number): number {\n if (maxFiles == null) {\n return CHAT_DEFAULT_FILE_UPLOAD_MAX_FILES;\n }\n\n return Math.max(1, maxFiles);\n}\n\nexport function useChatFileUpload({\n enabled = false,\n accept,\n maxFiles,\n onUploadFiles,\n disabled = false,\n}: UseChatFileUploadOptions) {\n const resolvedMaxFiles = resolveChatFileUploadMaxFiles(maxFiles);\n const active = enabled && Boolean(onUploadFiles) && !disabled;\n\n const {\n getRootProps: getDropzoneRootProps,\n getInputProps: getDropzoneInputProps,\n open,\n isDragActive,\n inputRef,\n } = useDropzone({\n accept,\n maxFiles: resolvedMaxFiles,\n multiple: resolvedMaxFiles > 1,\n disabled: !active,\n onDropAccepted: (files) => {\n if (onUploadFiles) {\n void onUploadFiles(files);\n }\n },\n });\n\n // Drag/drop root props WITHOUT a click handler — the `noClick` behaviour this hook used to\n // configure on react-dropzone. Clicking the chat surface must never open the file picker;\n // the attach button calls `open()` explicitly. Mirrors ui-solid's createChatFileUpload.\n const getRootProps = (): ChatFileUploadRootProps => {\n const { onClick: _onClick, ...rest } = getDropzoneRootProps();\n void _onClick;\n return rest;\n };\n\n const getInputProps = (extra?: { id?: string }): DropzoneInputProps & { id?: string } => ({\n ...getDropzoneInputProps(),\n ...(extra ?? {}),\n });\n\n const openFilePicker = () => {\n open();\n };\n\n return {\n enabled: active,\n maxFiles: resolvedMaxFiles,\n getRootProps,\n getInputProps,\n open: openFilePicker,\n inputRef,\n isDragActive,\n };\n}\n\nexport default useChatFileUpload;\n"],"names":["resolveChatFileUploadMaxFiles","maxFiles","CHAT_DEFAULT_FILE_UPLOAD_MAX_FILES","useChatFileUpload","enabled","accept","onUploadFiles","disabled","resolvedMaxFiles","active","getDropzoneRootProps","getDropzoneInputProps","open","isDragActive","inputRef","useDropzone","files","_onClick","rest","extra"],"mappings":";;AAqBO,SAASA,EAA8BC,GAA2B;AACvE,SAAIA,KAAY,OACPC,IAGF,KAAK,IAAI,GAAGD,CAAQ;AAC7B;AAEO,SAASE,EAAkB;AAAA,EAChC,SAAAC,IAAU;AAAA,EACV,QAAAC;AAAA,EACA,UAAAJ;AAAA,EACA,eAAAK;AAAA,EACA,UAAAC,IAAW;AACb,GAA6B;AAC3B,QAAMC,IAAmBR,EAA8BC,CAAQ,GACzDQ,IAASL,KAAW,EAAQE,KAAkB,CAACC,GAE/C;AAAA,IACJ,cAAcG;AAAA,IACd,eAAeC;AAAA,IACf,MAAAC;AAAA,IACA,cAAAC;AAAA,IACA,UAAAC;AAAA,EAAA,IACEC,EAAY;AAAA,IACd,QAAAV;AAAA,IACA,UAAUG;AAAA,IACV,UAAUA,IAAmB;AAAA,IAC7B,UAAU,CAACC;AAAA,IACX,gBAAgB,CAACO,MAAU;AACzB,MAAIV,KACGA,EAAcU,CAAK;AAAA,IAE5B;AAAA,EAAA,CACD;AAoBD,SAAO;AAAA,IACL,SAASP;AAAA,IACT,UAAUD;AAAA,IACV,cAlBmB,MAA+B;AAClD,YAAM,EAAE,SAASS,GAAU,GAAGC,EAAA,IAASR,EAAA;AAEvC,aAAOQ;AAAA,IACT;AAAA,IAeE,eAboB,CAACC,OAAmE;AAAA,MACxF,GAAGR,EAAA;AAAA,MACH,GAAIQ,KAAA,OAAAA,IAAS,CAAA;AAAA,IAAC;AAAA,IAYd,MATqB,MAAM;AAC3B,MAAAP,EAAA;AAAA,IACF;AAAA,IAQE,UAAAE;AAAA,IACA,cAAAD;AAAA,EAAA;AAEJ;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ConfirmDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
title: string;
|
|
5
|
+
/** The subject of the action, shown emphasised on its own line (e.g. the asset name). */
|
|
6
|
+
subject?: string;
|
|
7
|
+
/** A secondary explanatory line (e.g. "can't be undone"). */
|
|
8
|
+
message?: string;
|
|
9
|
+
confirmLabel: string;
|
|
10
|
+
cancelLabel?: string;
|
|
11
|
+
/** Style the confirm button as destructive (red). */
|
|
12
|
+
danger?: boolean;
|
|
13
|
+
/** Disable the actions + gate Esc/outside-click while a confirm is in flight. */
|
|
14
|
+
busy?: boolean;
|
|
15
|
+
onConfirm: () => void;
|
|
16
|
+
onCancel: () => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* An alert/confirm dialog built on {@link Modal}: a title, an optional emphasised subject + secondary
|
|
21
|
+
* message, and Cancel / Confirm actions. `role="alertdialog"` with the subject + message wired to
|
|
22
|
+
* `aria-describedby` so a screen reader announces the consequence, not just the title. While `busy`,
|
|
23
|
+
* Escape + outside-click are gated and the buttons disabled. Pure presentation — the caller owns the
|
|
24
|
+
* open state and the confirm/cancel handlers (and supplies localised labels).
|
|
25
|
+
*/
|
|
26
|
+
export declare function ConfirmDialog(props: ConfirmDialogProps): React.ReactElement;
|
|
27
|
+
export default ConfirmDialog;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsxs as a, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/confirmDialog/confirmDialog.entry.css';/* empty css */
|
|
3
|
+
import { useId as p } from "react";
|
|
4
|
+
import j from "clsx";
|
|
5
|
+
import { Modal as e } from "../modal/modal.js";
|
|
6
|
+
import { Typography as b } from "../../dataDisplay/typography/typography.js";
|
|
7
|
+
import { Button as f } from "../../inputs/button/button.js";
|
|
8
|
+
function _(u) {
|
|
9
|
+
const { open: y, title: t, subject: n, message: i, confirmLabel: C, cancelLabel: l, danger: h, busy: r, onConfirm: g, onCancel: s, className: x } = u, c = p(), d = p(), m = [n ? c : "", i ? d : ""].filter(Boolean).join(" ");
|
|
10
|
+
return /* @__PURE__ */ a(
|
|
11
|
+
e,
|
|
12
|
+
{
|
|
13
|
+
open: y,
|
|
14
|
+
onClose: s,
|
|
15
|
+
size: "small",
|
|
16
|
+
role: "alertdialog",
|
|
17
|
+
backdrop: "dark",
|
|
18
|
+
closeOnEsc: !r,
|
|
19
|
+
closeOnOutsideClick: !r,
|
|
20
|
+
"aria-label": t,
|
|
21
|
+
...m ? { "aria-describedby": m } : {},
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ o(e.Header, { children: t }),
|
|
24
|
+
/* @__PURE__ */ o(e.Content, { children: /* @__PURE__ */ a("div", { className: j("smwb-confirm-dialog__body", x), children: [
|
|
25
|
+
n ? /* @__PURE__ */ o(b, { id: c, variant: "body2", color: "textPrimary", component: "span", children: n }) : null,
|
|
26
|
+
i ? /* @__PURE__ */ o(b, { id: d, variant: "caption", color: "textSecondary", component: "span", children: i }) : null
|
|
27
|
+
] }) }),
|
|
28
|
+
/* @__PURE__ */ a(e.Footer, { children: [
|
|
29
|
+
/* @__PURE__ */ o(f, { variant: "text", size: "small", disabled: !!r, onClick: s, label: l != null ? l : "Cancel" }),
|
|
30
|
+
/* @__PURE__ */ o(
|
|
31
|
+
f,
|
|
32
|
+
{
|
|
33
|
+
variant: "contained",
|
|
34
|
+
size: "small",
|
|
35
|
+
color: h ? "error" : "primary",
|
|
36
|
+
disabled: !!r,
|
|
37
|
+
onClick: g,
|
|
38
|
+
label: C
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
] })
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
_ as ConfirmDialog
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=confirmDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmDialog.js","sources":["../../../../src/components/feedBack/confirmDialog/confirmDialog.tsx"],"sourcesContent":["import React, { useId } from \"react\";\nimport cn from \"clsx\";\nimport { Modal } from \"../modal\";\nimport { Button } from \"../../inputs/button\";\nimport { Typography } from \"../../dataDisplay/typography\";\n\nexport interface ConfirmDialogProps {\n open: boolean;\n title: string;\n /** The subject of the action, shown emphasised on its own line (e.g. the asset name). */\n subject?: string;\n /** A secondary explanatory line (e.g. \"can't be undone\"). */\n message?: string;\n confirmLabel: string;\n cancelLabel?: string;\n /** Style the confirm button as destructive (red). */\n danger?: boolean;\n /** Disable the actions + gate Esc/outside-click while a confirm is in flight. */\n busy?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n className?: string;\n}\n\n/**\n * An alert/confirm dialog built on {@link Modal}: a title, an optional emphasised subject + secondary\n * message, and Cancel / Confirm actions. `role=\"alertdialog\"` with the subject + message wired to\n * `aria-describedby` so a screen reader announces the consequence, not just the title. While `busy`,\n * Escape + outside-click are gated and the buttons disabled. Pure presentation — the caller owns the\n * open state and the confirm/cancel handlers (and supplies localised labels).\n */\nexport function ConfirmDialog(props: ConfirmDialogProps): React.ReactElement {\n const { open, title, subject, message, confirmLabel, cancelLabel, danger, busy, onConfirm, onCancel, className } =\n props;\n\n const subjectId = useId();\n const messageId = useId();\n // Only describe when there IS something to describe — an empty aria-describedby would point a\n // screen reader at nothing.\n const describedBy = [subject ? subjectId : \"\", message ? messageId : \"\"].filter(Boolean).join(\" \");\n\n return (\n <Modal\n open={open}\n onClose={onCancel}\n size=\"small\"\n role=\"alertdialog\"\n backdrop=\"dark\"\n closeOnEsc={!busy}\n closeOnOutsideClick={!busy}\n aria-label={title}\n {...(describedBy ? { \"aria-describedby\": describedBy } : {})}\n >\n <Modal.Header>{title}</Modal.Header>\n <Modal.Content>\n <div className={cn(\"smwb-confirm-dialog__body\", className)}>\n {subject ? (\n <Typography id={subjectId} variant=\"body2\" color=\"textPrimary\" component=\"span\">\n {subject}\n </Typography>\n ) : null}\n {message ? (\n <Typography id={messageId} variant=\"caption\" color=\"textSecondary\" component=\"span\">\n {message}\n </Typography>\n ) : null}\n </div>\n </Modal.Content>\n <Modal.Footer>\n <Button variant=\"text\" size=\"small\" disabled={!!busy} onClick={onCancel} label={cancelLabel ?? \"Cancel\"} />\n <Button\n variant=\"contained\"\n size=\"small\"\n color={danger ? \"error\" : \"primary\"}\n disabled={!!busy}\n onClick={onConfirm}\n label={confirmLabel}\n />\n </Modal.Footer>\n </Modal>\n );\n}\n\nexport default ConfirmDialog;\n"],"names":["ConfirmDialog","props","open","title","subject","message","confirmLabel","cancelLabel","danger","busy","onConfirm","onCancel","className","subjectId","useId","messageId","describedBy","jsxs","Modal","jsx","cn","Typography","Button"],"mappings":";;;;;;;AAgCO,SAASA,EAAcC,GAA+C;AAC3E,QAAM,EAAE,MAAAC,GAAM,OAAAC,GAAO,SAAAC,GAAS,SAAAC,GAAS,cAAAC,GAAc,aAAAC,GAAa,QAAAC,GAAQ,MAAAC,GAAM,WAAAC,GAAW,UAAAC,GAAU,WAAAC,EAAA,IACnGX,GAEIY,IAAYC,EAAA,GACZC,IAAYD,EAAA,GAGZE,IAAc,CAACZ,IAAUS,IAAY,IAAIR,IAAUU,IAAY,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAEjG,SACE,gBAAAE;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAAhB;AAAA,MACA,SAASS;AAAA,MACT,MAAK;AAAA,MACL,MAAK;AAAA,MACL,UAAS;AAAA,MACT,YAAY,CAACF;AAAA,MACb,qBAAqB,CAACA;AAAA,MACtB,cAAYN;AAAA,MACX,GAAIa,IAAc,EAAE,oBAAoBA,EAAA,IAAgB,CAAA;AAAA,MAEzD,UAAA;AAAA,QAAA,gBAAAG,EAACD,EAAM,QAAN,EAAc,UAAAf,EAAA,CAAM;AAAA,QACrB,gBAAAgB,EAACD,EAAM,SAAN,EACC,UAAA,gBAAAD,EAAC,SAAI,WAAWG,EAAG,6BAA6BR,CAAS,GACtD,UAAA;AAAA,UAAAR,IACC,gBAAAe,EAACE,GAAA,EAAW,IAAIR,GAAW,SAAQ,SAAQ,OAAM,eAAc,WAAU,QACtE,UAAAT,EAAA,CACH,IACE;AAAA,UACHC,IACC,gBAAAc,EAACE,GAAA,EAAW,IAAIN,GAAW,SAAQ,WAAU,OAAM,iBAAgB,WAAU,QAC1E,UAAAV,EAAA,CACH,IACE;AAAA,QAAA,EAAA,CACN,EAAA,CACF;AAAA,QACA,gBAAAY,EAACC,EAAM,QAAN,EACC,UAAA;AAAA,UAAA,gBAAAC,EAACG,GAAA,EAAO,SAAQ,QAAO,MAAK,SAAQ,UAAU,CAAC,CAACb,GAAM,SAASE,GAAU,OAAOJ,KAAA,OAAAA,IAAe,UAAU;AAAA,UACzG,gBAAAY;AAAA,YAACG;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,OAAOd,IAAS,UAAU;AAAA,cAC1B,UAAU,CAAC,CAACC;AAAA,cACZ,SAASC;AAAA,cACT,OAAOJ;AAAA,YAAA;AAAA,UAAA;AAAA,QACT,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import m from "clsx";
|
|
3
|
+
import { FloatingButton as t } from "../floatingButton/floatingButton.js";
|
|
4
|
+
import { Icon as p } from "../../base/icon/icon.js";
|
|
5
|
+
function w({ handleRemoveAll: o, filesLength: r, previewClassName: s, text: i }) {
|
|
6
|
+
const n = m("smwb-file-drop__preview", s);
|
|
7
|
+
return /* @__PURE__ */ l("div", { className: n, children: [
|
|
8
|
+
/* @__PURE__ */ e(t, { onClick: o, className: "smwb-file-drop__preview-button", children: /* @__PURE__ */ e(p, { name: "delete", size: 28 }) }),
|
|
9
|
+
/* @__PURE__ */ e("div", { className: "smwb-file-drop__preview-count", children: `${i || "uploaded files:"} ${r}` })
|
|
10
|
+
] });
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
w as CountPreview
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=countPreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"countPreview.js","sources":["../../../../src/components/inputs/fileDrop/countPreview.tsx"],"sourcesContent":["import { FloatingButton } from \"../floatingButton\";\nimport { Icon } from \"../../base/icon\";\nimport React from \"react\";\nimport cn from \"clsx\";\n\nexport interface CountPreviewProps {\n previewClassName?: string;\n text?: string;\n filesLength: number;\n handleRemoveAll: () => void;\n}\n\nexport function CountPreview({ handleRemoveAll, filesLength, previewClassName, text }: CountPreviewProps) {\n const previewClasses = cn(\"smwb-file-drop__preview\", previewClassName);\n\n return (\n <div className={previewClasses}>\n <FloatingButton onClick={handleRemoveAll} className=\"smwb-file-drop__preview-button\">\n <Icon name=\"delete\" size={28} />\n </FloatingButton>\n <div className=\"smwb-file-drop__preview-count\">{`${text ? text : \"uploaded files:\"} ${filesLength}`}</div>\n </div>\n );\n}\n"],"names":["CountPreview","handleRemoveAll","filesLength","previewClassName","text","previewClasses","cn","jsxs","jsx","FloatingButton","Icon"],"mappings":";;;;AAYO,SAASA,EAAa,EAAE,iBAAAC,GAAiB,aAAAC,GAAa,kBAAAC,GAAkB,MAAAC,KAA2B;AACxG,QAAMC,IAAiBC,EAAG,2BAA2BH,CAAgB;AAErE,SACE,gBAAAI,EAAC,OAAA,EAAI,WAAWF,GACd,UAAA;AAAA,IAAA,gBAAAG,EAACC,GAAA,EAAe,SAASR,GAAiB,WAAU,kCAClD,UAAA,gBAAAO,EAACE,GAAA,EAAK,MAAK,UAAS,MAAM,GAAA,CAAI,GAChC;AAAA,IACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,iCAAiC,UAAA,GAAGJ,KAAc,iBAAiB,IAAIF,CAAW,GAAA,CAAG;AAAA,EAAA,GACtG;AAEJ;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsxs as p, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/fileDrop/fileDrop.entry.css';/* empty css */
|
|
3
|
+
import g, { forwardRef as P } from "react";
|
|
4
|
+
import { useDropzone as R } from "../../../hooks/useDropzone.js";
|
|
5
|
+
import { PreviewWrapper as z } from "./previewWrapper.js";
|
|
6
|
+
import C from "clsx";
|
|
7
|
+
const U = P(function(a, n) {
|
|
8
|
+
const {
|
|
9
|
+
preview: d,
|
|
10
|
+
previewCols: m = 3,
|
|
11
|
+
galleryItemSize: c = 100,
|
|
12
|
+
onDrop: f,
|
|
13
|
+
label: s = "",
|
|
14
|
+
className: b,
|
|
15
|
+
previewClassName: w,
|
|
16
|
+
disabled: e,
|
|
17
|
+
error: o,
|
|
18
|
+
...u
|
|
19
|
+
} = a, [l, i] = g.useState([]), v = (t) => {
|
|
20
|
+
i((x) => [...x, ...t]), f(t);
|
|
21
|
+
}, { getRootProps: h, getInputProps: D } = R({
|
|
22
|
+
onDrop: v,
|
|
23
|
+
disabled: e,
|
|
24
|
+
...u
|
|
25
|
+
}), N = () => {
|
|
26
|
+
i([]);
|
|
27
|
+
}, _ = C("smwb-file-drop", { "smwb-disabled": e, "smwb-error": !!o }, b);
|
|
28
|
+
return /* @__PURE__ */ p("div", { ref: n, className: _, "data-testid": "file-drop", children: [
|
|
29
|
+
l.length > 0 ? /* @__PURE__ */ r(
|
|
30
|
+
z,
|
|
31
|
+
{
|
|
32
|
+
preview: d,
|
|
33
|
+
files: l,
|
|
34
|
+
handleRemoveAll: N,
|
|
35
|
+
previewCols: m,
|
|
36
|
+
galleryItemSize: c,
|
|
37
|
+
previewClassName: w
|
|
38
|
+
}
|
|
39
|
+
) : /* @__PURE__ */ p(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
className: "smwb-file-drop__input",
|
|
43
|
+
role: "button",
|
|
44
|
+
tabIndex: e ? -1 : 0,
|
|
45
|
+
"aria-disabled": e || void 0,
|
|
46
|
+
"aria-label": s || "Upload files",
|
|
47
|
+
...h(),
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ r("div", { className: "smwb-file-drop__input-text", children: s }),
|
|
50
|
+
/* @__PURE__ */ r("input", { ...D() })
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
),
|
|
54
|
+
o ? /* @__PURE__ */ r("span", { className: "smwb-file-drop__error", role: "alert", children: o }) : null
|
|
55
|
+
] });
|
|
56
|
+
});
|
|
57
|
+
export {
|
|
58
|
+
U as FileDrop
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=fileDrop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileDrop.js","sources":["../../../../src/components/inputs/fileDrop/fileDrop.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\";\nimport { type DropzoneOptions, useDropzone } from \"../../../hooks/useDropzone\";\nimport { PreviewWrapper } from \"./previewWrapper\";\nimport cn from \"clsx\";\n\nexport interface FileUploadProps extends DropzoneOptions {\n preview?: boolean;\n previewCols?: number;\n galleryItemSize?: number;\n onDrop: (files: File[]) => void;\n label?: string;\n className?: string;\n previewClassName?: string;\n disabled?: boolean;\n /** Validation message rendered below the drop zone. */\n error?: string;\n}\n\nexport const FileDrop = forwardRef<HTMLDivElement, FileUploadProps>(function FileDrop(props, ref) {\n const {\n preview,\n previewCols = 3,\n galleryItemSize = 100,\n onDrop: onDropProp,\n label = \"\",\n className,\n previewClassName,\n disabled,\n error,\n ...dropzoneOptions\n } = props;\n\n const [files, setFiles] = React.useState<File[]>([]);\n\n const onDrop = (acceptedFiles: File[]) => {\n setFiles((prev) => [...prev, ...acceptedFiles]);\n onDropProp(acceptedFiles);\n };\n\n const { getRootProps, getInputProps } = useDropzone({\n onDrop,\n disabled,\n ...dropzoneOptions,\n });\n\n const handleRemoveAll = () => {\n setFiles([]);\n };\n\n const wrapperClasses = cn(\"smwb-file-drop\", { \"smwb-disabled\": disabled, \"smwb-error\": !!error }, className);\n\n return (\n <div ref={ref} className={wrapperClasses} data-testid=\"file-drop\">\n {files.length > 0 ? (\n <PreviewWrapper\n preview={preview}\n files={files}\n handleRemoveAll={handleRemoveAll}\n previewCols={previewCols}\n galleryItemSize={galleryItemSize}\n previewClassName={previewClassName}\n />\n ) : (\n <div\n className=\"smwb-file-drop__input\"\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled || undefined}\n aria-label={label || \"Upload files\"}\n {...getRootProps()}\n >\n <div className=\"smwb-file-drop__input-text\">{label}</div>\n <input {...getInputProps()} />\n </div>\n )}\n {error ? (\n <span className=\"smwb-file-drop__error\" role=\"alert\">\n {error}\n </span>\n ) : null}\n </div>\n );\n});\n\nexport default FileDrop;\n"],"names":["FileDrop","forwardRef","props","ref","preview","previewCols","galleryItemSize","onDropProp","label","className","previewClassName","disabled","error","dropzoneOptions","files","setFiles","React","onDrop","acceptedFiles","prev","getRootProps","getInputProps","useDropzone","handleRemoveAll","wrapperClasses","cn","jsx","PreviewWrapper","jsxs"],"mappings":";;;;;;AAmBO,MAAMA,IAAWC,EAA4C,SAAkBC,GAAOC,GAAK;AAChG,QAAM;AAAA,IACJ,SAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,iBAAAC,IAAkB;AAAA,IAClB,QAAQC;AAAA,IACR,OAAAC,IAAQ;AAAA,IACR,WAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,IACDX,GAEE,CAACY,GAAOC,CAAQ,IAAIC,EAAM,SAAiB,CAAA,CAAE,GAE7CC,IAAS,CAACC,MAA0B;AACxC,IAAAH,EAAS,CAACI,MAAS,CAAC,GAAGA,GAAM,GAAGD,CAAa,CAAC,GAC9CX,EAAWW,CAAa;AAAA,EAC1B,GAEM,EAAE,cAAAE,GAAc,eAAAC,EAAA,IAAkBC,EAAY;AAAA,IAClD,QAAAL;AAAA,IACA,UAAAN;AAAA,IACA,GAAGE;AAAA,EAAA,CACJ,GAEKU,IAAkB,MAAM;AAC5B,IAAAR,EAAS,CAAA,CAAE;AAAA,EACb,GAEMS,IAAiBC,EAAG,kBAAkB,EAAE,iBAAiBd,GAAU,cAAc,CAAC,CAACC,EAAA,GAASH,CAAS;AAE3G,2BACG,OAAA,EAAI,KAAAN,GAAU,WAAWqB,GAAgB,eAAY,aACnD,UAAA;AAAA,IAAAV,EAAM,SAAS,IACd,gBAAAY;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,SAAAvB;AAAA,QACA,OAAAU;AAAA,QACA,iBAAAS;AAAA,QACA,aAAAlB;AAAA,QACA,iBAAAC;AAAA,QACA,kBAAAI;AAAA,MAAA;AAAA,IAAA,IAGF,gBAAAkB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAK;AAAA,QACL,UAAUjB,IAAW,KAAK;AAAA,QAC1B,iBAAeA,KAAY;AAAA,QAC3B,cAAYH,KAAS;AAAA,QACpB,GAAGY,EAAA;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAM,EAAC,OAAA,EAAI,WAAU,8BAA8B,UAAAlB,GAAM;AAAA,UACnD,gBAAAkB,EAAC,SAAA,EAAO,GAAGL,IAAc,CAAG;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAG/BT,sBACE,QAAA,EAAK,WAAU,yBAAwB,MAAK,SAC1C,aACH,IACE;AAAA,EAAA,GACN;AAEJ,CAAC;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { FileDrop, default } from "./fileDrop";
|
|
2
|
+
export type { FileUploadProps } from "./fileDrop";
|
|
3
|
+
export { PreviewWrapper } from "./previewWrapper";
|
|
4
|
+
export type { PreviewWrapperProps } from "./previewWrapper";
|
|
5
|
+
export { Preview } from "./preview";
|
|
6
|
+
export type { PreviewProps } from "./preview";
|
|
7
|
+
export { CountPreview } from "./countPreview";
|
|
8
|
+
export type { CountPreviewProps } from "./countPreview";
|
|
9
|
+
export { isImageFile } from "./utils";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsxs as p, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { isImageFile as c } from "./utils.js";
|
|
3
|
+
import w from "clsx";
|
|
4
|
+
import { FloatingButton as d } from "../floatingButton/floatingButton.js";
|
|
5
|
+
import { Icon as v } from "../../base/icon/icon.js";
|
|
6
|
+
import { ImagesList as f } from "../../dataDisplay/imagesList/imagesList.js";
|
|
7
|
+
import g from "../../dataDisplay/imagesList/imagesListItem/imagesListItem.js";
|
|
8
|
+
function C(i) {
|
|
9
|
+
const { files: o, handleRemoveAll: l, previewCols: t, galleryItemSize: s, previewClassName: a } = i, n = w("smwb-file-drop__preview", a);
|
|
10
|
+
return /* @__PURE__ */ p("div", { className: n, children: [
|
|
11
|
+
/* @__PURE__ */ r(d, { onClick: l, className: "smwb-file-drop__preview-button", children: /* @__PURE__ */ r(v, { name: "delete", size: 28 }) }),
|
|
12
|
+
/* @__PURE__ */ r(f, { className: "smwb-file-drop__preview-gallery", cols: t, rowsHeight: s, children: o.map((e) => {
|
|
13
|
+
const m = c(e) ? URL.createObjectURL(e) : null;
|
|
14
|
+
return m ? /* @__PURE__ */ r(
|
|
15
|
+
g,
|
|
16
|
+
{
|
|
17
|
+
className: "smwb-file-drop__preview-gallery-image",
|
|
18
|
+
src: m,
|
|
19
|
+
rows: 1,
|
|
20
|
+
cols: 1,
|
|
21
|
+
itemBarContent: e.name
|
|
22
|
+
},
|
|
23
|
+
e.name
|
|
24
|
+
) : /* @__PURE__ */ r(
|
|
25
|
+
"div",
|
|
26
|
+
{
|
|
27
|
+
className: "smwb-file-drop__preview-gallery-file",
|
|
28
|
+
style: {
|
|
29
|
+
width: `${s - 4}px`
|
|
30
|
+
},
|
|
31
|
+
children: e.name
|
|
32
|
+
},
|
|
33
|
+
e.name
|
|
34
|
+
);
|
|
35
|
+
}) })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
C as Preview
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview.js","sources":["../../../../src/components/inputs/fileDrop/preview.tsx"],"sourcesContent":["import { FloatingButton } from \"../floatingButton\";\nimport { Icon } from \"../../base/icon\";\nimport { ImagesList, ImagesListItem } from \"../../dataDisplay/imagesList\";\nimport { isImageFile } from \"./utils\";\nimport React from \"react\";\nimport cn from \"clsx\";\n\nexport interface PreviewProps {\n previewCols?: number;\n galleryItemSize?: number;\n previewClassName?: string;\n files: File[];\n handleRemoveAll: () => void;\n}\n\nexport function Preview(props: PreviewProps) {\n const { files, handleRemoveAll, previewCols, galleryItemSize, previewClassName } = props;\n\n const previewClasses = cn(\"smwb-file-drop__preview\", previewClassName);\n\n return (\n <div className={previewClasses}>\n <FloatingButton onClick={handleRemoveAll} className=\"smwb-file-drop__preview-button\">\n <Icon name=\"delete\" size={28} />\n </FloatingButton>\n <ImagesList className=\"smwb-file-drop__preview-gallery\" cols={previewCols as number} rowsHeight={galleryItemSize}>\n {files.map((file: File) => {\n const src = isImageFile(file) ? URL.createObjectURL(file) : null;\n\n return src ? (\n <ImagesListItem\n className=\"smwb-file-drop__preview-gallery-image\"\n key={file.name}\n src={src}\n rows={1}\n cols={1}\n itemBarContent={file.name}\n />\n ) : (\n <div\n key={file.name}\n className=\"smwb-file-drop__preview-gallery-file\"\n style={{\n width: `${(galleryItemSize as number) - 4}px`,\n }}\n >\n {file.name}\n </div>\n );\n })}\n </ImagesList>\n </div>\n );\n}\n"],"names":["Preview","props","files","handleRemoveAll","previewCols","galleryItemSize","previewClassName","previewClasses","cn","jsxs","jsx","FloatingButton","Icon","ImagesList","file","src","isImageFile","ImagesListItem"],"mappings":";;;;;;;AAeO,SAASA,EAAQC,GAAqB;AAC3C,QAAM,EAAE,OAAAC,GAAO,iBAAAC,GAAiB,aAAAC,GAAa,iBAAAC,GAAiB,kBAAAC,MAAqBL,GAE7EM,IAAiBC,EAAG,2BAA2BF,CAAgB;AAErE,SACE,gBAAAG,EAAC,OAAA,EAAI,WAAWF,GACd,UAAA;AAAA,IAAA,gBAAAG,EAACC,GAAA,EAAe,SAASR,GAAiB,WAAU,kCAClD,UAAA,gBAAAO,EAACE,GAAA,EAAK,MAAK,UAAS,MAAM,GAAA,CAAI,GAChC;AAAA,IACA,gBAAAF,EAACG,GAAA,EAAW,WAAU,mCAAkC,MAAMT,GAAuB,YAAYC,GAC9F,UAAAH,EAAM,IAAI,CAACY,MAAe;AACzB,YAAMC,IAAMC,EAAYF,CAAI,IAAI,IAAI,gBAAgBA,CAAI,IAAI;AAE5D,aAAOC,IACL,gBAAAL;AAAA,QAACO;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UAEV,KAAAF;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN,gBAAgBD,EAAK;AAAA,QAAA;AAAA,QAJhBA,EAAK;AAAA,MAAA,IAOZ,gBAAAJ;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,OAAO,GAAIL,IAA6B,CAAC;AAAA,UAAA;AAAA,UAG1C,UAAAS,EAAK;AAAA,QAAA;AAAA,QANDA,EAAK;AAAA,MAAA;AAAA,IAShB,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as e, Fragment as p } from "react/jsx-runtime";
|
|
2
|
+
import { Preview as s } from "./preview.js";
|
|
3
|
+
import { CountPreview as v } from "./countPreview.js";
|
|
4
|
+
function g(t) {
|
|
5
|
+
const { previewCols: l, preview: m, galleryItemSize: n, handleRemoveAll: r, files: i, previewClassName: o } = t;
|
|
6
|
+
return /* @__PURE__ */ e(p, { children: m ? /* @__PURE__ */ e(
|
|
7
|
+
s,
|
|
8
|
+
{
|
|
9
|
+
files: i,
|
|
10
|
+
handleRemoveAll: r,
|
|
11
|
+
previewCols: l,
|
|
12
|
+
galleryItemSize: n,
|
|
13
|
+
previewClassName: o
|
|
14
|
+
}
|
|
15
|
+
) : /* @__PURE__ */ e(
|
|
16
|
+
v,
|
|
17
|
+
{
|
|
18
|
+
filesLength: i.length,
|
|
19
|
+
handleRemoveAll: r,
|
|
20
|
+
previewClassName: o
|
|
21
|
+
}
|
|
22
|
+
) });
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
g as PreviewWrapper
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=previewWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previewWrapper.js","sources":["../../../../src/components/inputs/fileDrop/previewWrapper.tsx"],"sourcesContent":["import { Preview } from \"./preview\";\nimport { CountPreview } from \"./countPreview\";\nimport React from \"react\";\n\nexport interface PreviewWrapperProps {\n preview?: boolean;\n files: File[];\n handleRemoveAll: () => void;\n previewCols?: number;\n galleryItemSize?: number;\n previewClassName?: string;\n}\n\nexport function PreviewWrapper(props: PreviewWrapperProps) {\n const { previewCols, preview, galleryItemSize, handleRemoveAll, files, previewClassName } = props;\n\n return (\n <>\n {preview ? (\n <Preview\n files={files}\n handleRemoveAll={handleRemoveAll}\n previewCols={previewCols}\n galleryItemSize={galleryItemSize}\n previewClassName={previewClassName}\n />\n ) : (\n <CountPreview\n filesLength={files.length}\n handleRemoveAll={handleRemoveAll}\n previewClassName={previewClassName}\n />\n )}\n </>\n );\n}\n"],"names":["PreviewWrapper","props","previewCols","preview","galleryItemSize","handleRemoveAll","files","previewClassName","jsx","Preview","CountPreview"],"mappings":";;;AAaO,SAASA,EAAeC,GAA4B;AACzD,QAAM,EAAE,aAAAC,GAAa,SAAAC,GAAS,iBAAAC,GAAiB,iBAAAC,GAAiB,OAAAC,GAAO,kBAAAC,MAAqBN;AAE5F,gCAEK,UAAAE,IACC,gBAAAK;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAAH;AAAA,MACA,iBAAAD;AAAA,MACA,aAAAH;AAAA,MACA,iBAAAE;AAAA,MACA,kBAAAG;AAAA,IAAA;AAAA,EAAA,IAGF,gBAAAC;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,aAAaJ,EAAM;AAAA,MACnB,iBAAAD;AAAA,MACA,kBAAAE;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/components/inputs/fileDrop/utils.ts"],"sourcesContent":["export function isImageFile(file: File): boolean {\n return /^image\\/(png|jpeg)$/.test(file.type);\n}\n"],"names":["isImageFile","file"],"mappings":"AAAO,SAASA,EAAYC,GAAqB;AAC/C,SAAO,sBAAsB,KAAKA,EAAK,IAAI;AAC7C;"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsxs as w, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import '../../../assets/styles/less/components/fileInput/fileInput.entry.css';/* empty css */
|
|
3
|
+
import { forwardRef as x } from "react";
|
|
4
|
+
import { useDropzone as D } from "../../../hooks/useDropzone.js";
|
|
5
|
+
import p from "clsx";
|
|
6
|
+
const R = x(function(a, m) {
|
|
7
|
+
const { label: c, onClick: o, onFilesSelected: e, className: u, buttonClassName: d, disabled: s, error: i, ...t } = a, { getRootProps: f, getInputProps: b } = D({
|
|
8
|
+
...t,
|
|
9
|
+
disabled: s,
|
|
10
|
+
onDropAccepted: (r, h) => {
|
|
11
|
+
var l;
|
|
12
|
+
e == null || e(r), (l = t.onDropAccepted) == null || l.call(t, r, h);
|
|
13
|
+
}
|
|
14
|
+
}), N = (r) => {
|
|
15
|
+
o == null || o(r);
|
|
16
|
+
};
|
|
17
|
+
return /* @__PURE__ */ w(
|
|
18
|
+
"div",
|
|
19
|
+
{
|
|
20
|
+
ref: m,
|
|
21
|
+
className: p("smwb-file-input", { "smwb-disabled": s }, u),
|
|
22
|
+
"data-testid": "file-input",
|
|
23
|
+
...f(),
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ n("button", { type: "button", className: p(d), disabled: s, onClick: N, children: c }),
|
|
26
|
+
/* @__PURE__ */ n("input", { ...b() }),
|
|
27
|
+
i ? /* @__PURE__ */ n("span", { className: "smwb-file-input__error", role: "alert", children: i }) : null
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
export {
|
|
33
|
+
R as FileInput
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=fileInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileInput.js","sources":["../../../../src/components/inputs/fileInput/fileInput.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\";\nimport { type DropzoneOptions, useDropzone } from \"../../../hooks/useDropzone\";\nimport cn from \"clsx\";\n\nexport interface FileInputProps extends DropzoneOptions {\n label?: string;\n className?: string;\n buttonClassName?: string;\n disabled?: boolean;\n /** Validation message shown below the control. */\n error?: string;\n /** Fired with the accepted files when the user picks them. */\n onFilesSelected?: (files: File[]) => void;\n /** @deprecated optional click passthrough on the trigger button. */\n onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n}\n\nexport const FileInput = forwardRef<HTMLDivElement, FileInputProps>(function FileInput(props, ref) {\n const { label, onClick, onFilesSelected, className, buttonClassName, disabled, error, ...dropzoneOptions } = props;\n\n const { getRootProps, getInputProps } = useDropzone({\n ...dropzoneOptions,\n disabled,\n onDropAccepted: (accepted, event) => {\n onFilesSelected?.(accepted);\n dropzoneOptions.onDropAccepted?.(accepted, event);\n },\n });\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n };\n\n return (\n <div\n ref={ref}\n className={cn(\"smwb-file-input\", { \"smwb-disabled\": disabled }, className)}\n data-testid=\"file-input\"\n {...getRootProps()}\n >\n <button type=\"button\" className={cn(buttonClassName)} disabled={disabled} onClick={handleClick}>\n {label}\n </button>\n <input {...getInputProps()} />\n {error ? (\n <span className=\"smwb-file-input__error\" role=\"alert\">\n {error}\n </span>\n ) : null}\n </div>\n );\n});\n\nexport default FileInput;\n"],"names":["FileInput","forwardRef","props","ref","label","onClick","onFilesSelected","className","buttonClassName","disabled","error","dropzoneOptions","getRootProps","getInputProps","useDropzone","accepted","event","_a","handleClick","e","jsxs","cn","jsx"],"mappings":";;;;;AAkBO,MAAMA,IAAYC,EAA2C,SAAmBC,GAAOC,GAAK;AACjG,QAAM,EAAE,OAAAC,GAAO,SAAAC,GAAS,iBAAAC,GAAiB,WAAAC,GAAW,iBAAAC,GAAiB,UAAAC,GAAU,OAAAC,GAAO,GAAGC,EAAA,IAAoBT,GAEvG,EAAE,cAAAU,GAAc,eAAAC,EAAA,IAAkBC,EAAY;AAAA,IAClD,GAAGH;AAAA,IACH,UAAAF;AAAA,IACA,gBAAgB,CAACM,GAAUC,MAAU;;AACnC,MAAAV,KAAA,QAAAA,EAAkBS,KAClBE,IAAAN,EAAgB,mBAAhB,QAAAM,EAAA,KAAAN,GAAiCI,GAAUC;AAAA,IAC7C;AAAA,EAAA,CACD,GAEKE,IAAc,CAACC,MAA2C;AAC9D,IAAAd,KAAA,QAAAA,EAAUc;AAAA,EACZ;AAEA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAjB;AAAA,MACA,WAAWkB,EAAG,mBAAmB,EAAE,iBAAiBZ,EAAA,GAAYF,CAAS;AAAA,MACzE,eAAY;AAAA,MACX,GAAGK,EAAA;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAAU,EAAC,UAAA,EAAO,MAAK,UAAS,WAAWD,EAAGb,CAAe,GAAG,UAAAC,GAAoB,SAASS,GAChF,UAAAd,EAAA,CACH;AAAA,QACA,gBAAAkB,EAAC,SAAA,EAAO,GAAGT,EAAA,EAAc,CAAG;AAAA,QAC3BH,sBACE,QAAA,EAAK,WAAU,0BAAyB,MAAK,SAC3C,aACH,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;"}
|