index.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { h, type ComponentChild } from 'preact'
  2. import copyToClipboard from '../../../utils/copyToClipboard.ts'
  3. type $TSFixMe = any
  4. function EditButton({
  5. file,
  6. uploadInProgressOrComplete,
  7. metaFields,
  8. canEditFile,
  9. i18n,
  10. onClick,
  11. }: $TSFixMe) {
  12. if (
  13. (!uploadInProgressOrComplete && metaFields && metaFields.length > 0) ||
  14. (!uploadInProgressOrComplete && canEditFile(file))
  15. ) {
  16. return (
  17. <button
  18. className="uppy-u-reset uppy-c-btn uppy-Dashboard-Item-action uppy-Dashboard-Item-action--edit"
  19. type="button"
  20. aria-label={i18n('editFileWithFilename', { file: file.meta.name })}
  21. title={i18n('editFileWithFilename', { file: file.meta.name })}
  22. onClick={() => onClick()}
  23. >
  24. <svg
  25. aria-hidden="true"
  26. focusable="false"
  27. className="uppy-c-icon"
  28. width="14"
  29. height="14"
  30. viewBox="0 0 14 14"
  31. >
  32. <g fillRule="evenodd">
  33. <path
  34. d="M1.5 10.793h2.793A1 1 0 0 0 5 10.5L11.5 4a1 1 0 0 0 0-1.414L9.707.793a1 1 0 0 0-1.414 0l-6.5 6.5A1 1 0 0 0 1.5 8v2.793zm1-1V8L9 1.5l1.793 1.793-6.5 6.5H2.5z"
  35. fillRule="nonzero"
  36. />
  37. <rect x="1" y="12.293" width="11" height="1" rx=".5" />
  38. <path
  39. fillRule="nonzero"
  40. d="M6.793 2.5L9.5 5.207l.707-.707L7.5 1.793z"
  41. />
  42. </g>
  43. </svg>
  44. </button>
  45. )
  46. }
  47. return null
  48. }
  49. function RemoveButton({ i18n, onClick, file }: $TSFixMe) {
  50. return (
  51. <button
  52. className="uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--remove"
  53. type="button"
  54. aria-label={i18n('removeFile', { file: file.meta.name })}
  55. title={i18n('removeFile', { file: file.meta.name })}
  56. onClick={() => onClick()}
  57. >
  58. <svg
  59. aria-hidden="true"
  60. focusable="false"
  61. className="uppy-c-icon"
  62. width="18"
  63. height="18"
  64. viewBox="0 0 18 18"
  65. >
  66. <path d="M9 0C4.034 0 0 4.034 0 9s4.034 9 9 9 9-4.034 9-9-4.034-9-9-9z" />
  67. <path
  68. fill="#FFF"
  69. d="M13 12.222l-.778.778L9 9.778 5.778 13 5 12.222 8.222 9 5 5.778 5.778 5 9 8.222 12.222 5l.778.778L9.778 9z"
  70. />
  71. </svg>
  72. </button>
  73. )
  74. }
  75. const copyLinkToClipboard = (event: $TSFixMe, props: $TSFixMe) => {
  76. copyToClipboard(
  77. props.file.uploadURL,
  78. props.i18n('copyLinkToClipboardFallback'),
  79. )
  80. .then(() => {
  81. props.uppy.log('Link copied to clipboard.')
  82. props.uppy.info(props.i18n('copyLinkToClipboardSuccess'), 'info', 3000)
  83. })
  84. .catch(props.uppy.log)
  85. // avoid losing focus
  86. .then(() => event.target.focus({ preventScroll: true }))
  87. }
  88. function CopyLinkButton(props: $TSFixMe) {
  89. const { i18n } = props
  90. return (
  91. <button
  92. className="uppy-u-reset uppy-Dashboard-Item-action uppy-Dashboard-Item-action--copyLink"
  93. type="button"
  94. aria-label={i18n('copyLink')}
  95. title={i18n('copyLink')}
  96. onClick={(event) => copyLinkToClipboard(event, props)}
  97. >
  98. <svg
  99. aria-hidden="true"
  100. focusable="false"
  101. className="uppy-c-icon"
  102. width="14"
  103. height="14"
  104. viewBox="0 0 14 12"
  105. >
  106. <path d="M7.94 7.703a2.613 2.613 0 0 1-.626 2.681l-.852.851a2.597 2.597 0 0 1-1.849.766A2.616 2.616 0 0 1 2.764 7.54l.852-.852a2.596 2.596 0 0 1 2.69-.625L5.267 7.099a1.44 1.44 0 0 0-.833.407l-.852.851a1.458 1.458 0 0 0 1.03 2.486c.39 0 .755-.152 1.03-.426l.852-.852c.231-.231.363-.522.406-.824l1.04-1.038zm4.295-5.937A2.596 2.596 0 0 0 10.387 1c-.698 0-1.355.272-1.849.766l-.852.851a2.614 2.614 0 0 0-.624 2.688l1.036-1.036c.041-.304.173-.6.407-.833l.852-.852c.275-.275.64-.426 1.03-.426a1.458 1.458 0 0 1 1.03 2.486l-.852.851a1.442 1.442 0 0 1-.824.406l-1.04 1.04a2.596 2.596 0 0 0 2.683-.628l.851-.85a2.616 2.616 0 0 0 0-3.697zm-6.88 6.883a.577.577 0 0 0 .82 0l3.474-3.474a.579.579 0 1 0-.819-.82L5.355 7.83a.579.579 0 0 0 0 .819z" />
  107. </svg>
  108. </button>
  109. )
  110. }
  111. export default function Buttons(props: $TSFixMe): ComponentChild {
  112. const {
  113. uppy,
  114. file,
  115. uploadInProgressOrComplete,
  116. canEditFile,
  117. metaFields,
  118. showLinkToFileUploadResult,
  119. showRemoveButton,
  120. i18n,
  121. toggleFileCard,
  122. openFileEditor,
  123. } = props
  124. const editAction = () => {
  125. if (metaFields && metaFields.length > 0) {
  126. toggleFileCard(true, file.id)
  127. } else {
  128. openFileEditor(file)
  129. }
  130. }
  131. return (
  132. <div className="uppy-Dashboard-Item-actionWrapper">
  133. <EditButton
  134. i18n={i18n}
  135. file={file}
  136. uploadInProgressOrComplete={uploadInProgressOrComplete}
  137. canEditFile={canEditFile}
  138. metaFields={metaFields}
  139. onClick={editAction}
  140. />
  141. {showLinkToFileUploadResult && file.uploadURL ?
  142. <CopyLinkButton file={file} uppy={uppy} i18n={i18n} />
  143. : null}
  144. {showRemoveButton ?
  145. <RemoveButton
  146. i18n={i18n}
  147. file={file}
  148. uppy={uppy}
  149. onClick={() => uppy.removeFile(file.id, 'removed-by-user')}
  150. />
  151. : null}
  152. </div>
  153. )
  154. }