@openrails/contentkit-ui 0.103.2 → 0.104.0-rc.2

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 (253) hide show
  1. package/README.md +111 -49
  2. package/dist/client/beacons.d.ts +3 -13
  3. package/dist/client/beacons.js +8 -46
  4. package/dist/client/beacons.js.map +1 -1
  5. package/dist/client/client.d.ts +3 -0
  6. package/dist/client/client.js +45 -43
  7. package/dist/client/client.js.map +1 -1
  8. package/dist/client/content/favorites.d.ts +2 -0
  9. package/dist/client/content/favorites.js.map +1 -1
  10. package/dist/client/content/types.d.ts +3 -0
  11. package/dist/client/content/types.js.map +1 -1
  12. package/dist/client/contents.d.ts +7 -1
  13. package/dist/client/contents.js +8 -0
  14. package/dist/client/contents.js.map +1 -1
  15. package/dist/client/discovery.d.ts +34 -5
  16. package/dist/client/discovery.js +23 -2
  17. package/dist/client/discovery.js.map +1 -1
  18. package/dist/client/engagement.d.ts +70 -0
  19. package/dist/client/engagement.js +191 -0
  20. package/dist/client/engagement.js.map +1 -0
  21. package/dist/client/generated/routes.d.ts +74 -35
  22. package/dist/client/generated/routes.js +119 -60
  23. package/dist/client/generated/routes.js.map +1 -1
  24. package/dist/client/generated/wire.d.ts +88 -85
  25. package/dist/client/generated/wire.js.map +1 -1
  26. package/dist/client/guest-reading-history.d.ts +40 -0
  27. package/dist/client/guest-reading-history.js +144 -0
  28. package/dist/client/guest-reading-history.js.map +1 -0
  29. package/dist/client/index.d.ts +5 -3
  30. package/dist/client/media/windows.d.ts +2 -0
  31. package/dist/client/media/windows.js +4 -1
  32. package/dist/client/media/windows.js.map +1 -1
  33. package/dist/client/stats.d.ts +4 -20
  34. package/dist/client/stats.js +0 -11
  35. package/dist/client/stats.js.map +1 -1
  36. package/dist/client/versions.d.ts +8 -6
  37. package/dist/client/versions.js +15 -10
  38. package/dist/client/versions.js.map +1 -1
  39. package/dist/client.js +24 -22
  40. package/dist/components/admin/bulk-drafts.d.ts +17 -0
  41. package/dist/components/admin/bulk-drafts.js +41 -0
  42. package/dist/components/admin/bulk-drafts.js.map +1 -0
  43. package/dist/components/admin/content-admin.d.ts +1 -1
  44. package/dist/components/admin/content-admin.js.map +1 -1
  45. package/dist/components/admin/content-manager.d.ts +11 -3
  46. package/dist/components/admin/content-manager.js +751 -394
  47. package/dist/components/admin/content-manager.js.map +1 -1
  48. package/dist/components/admin/group-manager.d.ts +8 -3
  49. package/dist/components/admin/group-manager.js +218 -146
  50. package/dist/components/admin/group-manager.js.map +1 -1
  51. package/dist/components/admin/page-notices.d.ts +16 -0
  52. package/dist/components/admin/page-notices.js +113 -0
  53. package/dist/components/admin/page-notices.js.map +1 -0
  54. package/dist/components/admin/page-picker.d.ts +38 -0
  55. package/dist/components/admin/page-picker.js +159 -0
  56. package/dist/components/admin/page-picker.js.map +1 -0
  57. package/dist/components/admin/quick-search.d.ts +14 -0
  58. package/dist/components/admin/quick-search.js +60 -0
  59. package/dist/components/admin/quick-search.js.map +1 -0
  60. package/dist/components/admin/reader-content-editor.js +382 -321
  61. package/dist/components/admin/reader-content-editor.js.map +1 -1
  62. package/dist/components/admin/reader-manifest.js +181 -179
  63. package/dist/components/admin/reader-manifest.js.map +1 -1
  64. package/dist/components/admin/shell.d.ts +10 -2
  65. package/dist/components/admin/shell.js +114 -42
  66. package/dist/components/admin/shell.js.map +1 -1
  67. package/dist/components/admin/stats-dashboard.d.ts +4 -9
  68. package/dist/components/admin/stats-dashboard.js +303 -207
  69. package/dist/components/admin/stats-dashboard.js.map +1 -1
  70. package/dist/components/admin/upload-queue.d.ts +14 -0
  71. package/dist/components/admin/upload-queue.js +115 -98
  72. package/dist/components/admin/upload-queue.js.map +1 -1
  73. package/dist/components/content/card.d.ts +31 -3
  74. package/dist/components/content/card.js +324 -158
  75. package/dist/components/content/card.js.map +1 -1
  76. package/dist/components/content/daily-releases.js +144 -190
  77. package/dist/components/content/daily-releases.js.map +1 -1
  78. package/dist/components/content/editor-save.js +27 -25
  79. package/dist/components/content/editor-save.js.map +1 -1
  80. package/dist/components/content/editors.js +274 -253
  81. package/dist/components/content/editors.js.map +1 -1
  82. package/dist/components/content/favorites.d.ts +6 -0
  83. package/dist/components/content/favorites.js +47 -0
  84. package/dist/components/content/favorites.js.map +1 -0
  85. package/dist/components/content/filter-dialog.js +19 -15
  86. package/dist/components/content/filter-dialog.js.map +1 -1
  87. package/dist/components/content/filters.d.ts +2 -0
  88. package/dist/components/content/filters.js +5 -1
  89. package/dist/components/content/filters.js.map +1 -1
  90. package/dist/components/content/grid.d.ts +44 -16
  91. package/dist/components/content/grid.js +308 -270
  92. package/dist/components/content/grid.js.map +1 -1
  93. package/dist/components/content/history.d.ts +6 -0
  94. package/dist/components/content/history.js +111 -0
  95. package/dist/components/content/history.js.map +1 -0
  96. package/dist/components/content/index.d.ts +6 -3
  97. package/dist/components/content/listing.d.ts +14 -3
  98. package/dist/components/content/listing.js +65 -56
  99. package/dist/components/content/listing.js.map +1 -1
  100. package/dist/components/content/offer-fields.js +6 -6
  101. package/dist/components/content/paged-grid.d.ts +10 -0
  102. package/dist/components/content/paged-grid.js +116 -0
  103. package/dist/components/content/paged-grid.js.map +1 -0
  104. package/dist/components/content/pagination.d.ts +19 -0
  105. package/dist/components/content/pagination.js +97 -0
  106. package/dist/components/content/pagination.js.map +1 -0
  107. package/dist/components/content/paywall.d.ts +9 -0
  108. package/dist/components/content/paywall.js +27 -3
  109. package/dist/components/content/paywall.js.map +1 -1
  110. package/dist/components/content/post-list.d.ts +37 -0
  111. package/dist/components/content/post-list.js +203 -0
  112. package/dist/components/content/post-list.js.map +1 -0
  113. package/dist/components/content/reader-settings.d.ts +2 -0
  114. package/dist/components/content/reader-settings.js +1 -1
  115. package/dist/components/content/reader-settings.js.map +1 -1
  116. package/dist/components/content/search.d.ts +11 -4
  117. package/dist/components/content/search.js +22 -11
  118. package/dist/components/content/search.js.map +1 -1
  119. package/dist/components/content/summary-tile.d.ts +14 -0
  120. package/dist/components/content/summary-tile.js +63 -0
  121. package/dist/components/content/summary-tile.js.map +1 -0
  122. package/dist/components/groups/banner.d.ts +6 -2
  123. package/dist/components/groups/banner.js +79 -61
  124. package/dist/components/groups/banner.js.map +1 -1
  125. package/dist/components/groups/directory.d.ts +12 -2
  126. package/dist/components/groups/directory.js +168 -105
  127. package/dist/components/groups/directory.js.map +1 -1
  128. package/dist/components/groups/editor.js +10 -10
  129. package/dist/components/groups/editor.js.map +1 -1
  130. package/dist/components/groups/entity-chips.d.ts +61 -0
  131. package/dist/components/groups/entity-chips.js +382 -0
  132. package/dist/components/groups/entity-chips.js.map +1 -0
  133. package/dist/components/groups/group-members.d.ts +29 -0
  134. package/dist/components/groups/group-members.js +474 -0
  135. package/dist/components/groups/group-members.js.map +1 -0
  136. package/dist/components/groups/header.js +53 -45
  137. package/dist/components/groups/header.js.map +1 -1
  138. package/dist/components/groups/index.d.ts +3 -1
  139. package/dist/components/groups/memberships.d.ts +3 -36
  140. package/dist/components/groups/memberships.js +105 -480
  141. package/dist/components/groups/memberships.js.map +1 -1
  142. package/dist/components/groups/scoped.d.ts +23 -0
  143. package/dist/components/groups/scoped.js +92 -0
  144. package/dist/components/groups/scoped.js.map +1 -0
  145. package/dist/components/media-folder-editor.d.ts +5 -0
  146. package/dist/components/media-folder-editor.js +419 -231
  147. package/dist/components/media-folder-editor.js.map +1 -1
  148. package/dist/components/sortable-list.d.ts +5 -1
  149. package/dist/components/sortable-list.js +97 -81
  150. package/dist/components/sortable-list.js.map +1 -1
  151. package/dist/components/video-mini-player.d.ts +4 -1
  152. package/dist/components/video-mini-player.js +77 -71
  153. package/dist/components/video-mini-player.js.map +1 -1
  154. package/dist/components/video-player.d.ts +4 -1
  155. package/dist/components/video-player.js +280 -276
  156. package/dist/components/video-player.js.map +1 -1
  157. package/dist/index.d.ts +2 -1
  158. package/dist/index.js +41 -34
  159. package/dist/locales/admin/de.js +80 -47
  160. package/dist/locales/admin/de.js.map +1 -1
  161. package/dist/locales/admin/en.d.ts +74 -41
  162. package/dist/locales/admin/en.js +80 -47
  163. package/dist/locales/admin/en.js.map +1 -1
  164. package/dist/locales/admin/es.js +80 -47
  165. package/dist/locales/admin/es.js.map +1 -1
  166. package/dist/locales/admin/ja.js +80 -47
  167. package/dist/locales/admin/ja.js.map +1 -1
  168. package/dist/locales/admin/ko.js +80 -47
  169. package/dist/locales/admin/ko.js.map +1 -1
  170. package/dist/locales/admin/zh.js +80 -47
  171. package/dist/locales/admin/zh.js.map +1 -1
  172. package/dist/locales/de.js +1 -0
  173. package/dist/locales/de.js.map +1 -1
  174. package/dist/locales/discovery/de.js +25 -2
  175. package/dist/locales/discovery/de.js.map +1 -1
  176. package/dist/locales/discovery/en.d.ts +24 -1
  177. package/dist/locales/discovery/en.js +25 -2
  178. package/dist/locales/discovery/en.js.map +1 -1
  179. package/dist/locales/discovery/es.js +25 -2
  180. package/dist/locales/discovery/es.js.map +1 -1
  181. package/dist/locales/discovery/ja.js +25 -2
  182. package/dist/locales/discovery/ja.js.map +1 -1
  183. package/dist/locales/discovery/ko.js +25 -2
  184. package/dist/locales/discovery/ko.js.map +1 -1
  185. package/dist/locales/discovery/zh.js +25 -2
  186. package/dist/locales/discovery/zh.js.map +1 -1
  187. package/dist/locales/en.d.ts +119 -44
  188. package/dist/locales/en.js +1 -0
  189. package/dist/locales/en.js.map +1 -1
  190. package/dist/locales/es.js +1 -0
  191. package/dist/locales/es.js.map +1 -1
  192. package/dist/locales/groups/de.js +22 -4
  193. package/dist/locales/groups/de.js.map +1 -1
  194. package/dist/locales/groups/en.d.ts +20 -2
  195. package/dist/locales/groups/en.js +22 -4
  196. package/dist/locales/groups/en.js.map +1 -1
  197. package/dist/locales/groups/es.js +22 -4
  198. package/dist/locales/groups/es.js.map +1 -1
  199. package/dist/locales/groups/ja.js +22 -4
  200. package/dist/locales/groups/ja.js.map +1 -1
  201. package/dist/locales/groups/ko.js +22 -4
  202. package/dist/locales/groups/ko.js.map +1 -1
  203. package/dist/locales/groups/zh.js +22 -4
  204. package/dist/locales/groups/zh.js.map +1 -1
  205. package/dist/locales/ja.js +1 -0
  206. package/dist/locales/ja.js.map +1 -1
  207. package/dist/locales/ko.js +1 -0
  208. package/dist/locales/ko.js.map +1 -1
  209. package/dist/locales/zh.js +1 -0
  210. package/dist/locales/zh.js.map +1 -1
  211. package/dist/react/discovery.d.ts +36 -17
  212. package/dist/react/discovery.js +305 -221
  213. package/dist/react/discovery.js.map +1 -1
  214. package/dist/react/groups.d.ts +19 -3
  215. package/dist/react/groups.js +49 -22
  216. package/dist/react/groups.js.map +1 -1
  217. package/dist/react/index.d.ts +7 -4
  218. package/dist/react/page-notices.d.ts +13 -0
  219. package/dist/react/page-notices.js +38 -0
  220. package/dist/react/page-notices.js.map +1 -0
  221. package/dist/react/post-reads.d.ts +23 -0
  222. package/dist/react/post-reads.js +90 -0
  223. package/dist/react/post-reads.js.map +1 -0
  224. package/dist/react/remembered-sort.d.ts +5 -0
  225. package/dist/react/remembered-sort.js +29 -0
  226. package/dist/react/remembered-sort.js.map +1 -0
  227. package/dist/react/resources.d.ts +3 -1
  228. package/dist/react/resources.js +6 -2
  229. package/dist/react/resources.js.map +1 -1
  230. package/dist/react/stats.d.ts +3 -7
  231. package/dist/react/stats.js +2 -6
  232. package/dist/react/stats.js.map +1 -1
  233. package/dist/react/use-engagement.d.ts +28 -0
  234. package/dist/react/use-engagement.js +226 -0
  235. package/dist/react/use-engagement.js.map +1 -0
  236. package/dist/react/use-resource.d.ts +4 -3
  237. package/dist/react/use-resource.js +2 -1
  238. package/dist/react/use-resource.js.map +1 -1
  239. package/dist/react.js +29 -26
  240. package/dist/styles.css +1 -1
  241. package/dist/ui/dialog.d.ts +2 -1
  242. package/dist/ui/dialog.js +23 -20
  243. package/dist/ui/dialog.js.map +1 -1
  244. package/dist/urls/index.d.ts +1 -1
  245. package/dist/urls.js +2 -2
  246. package/dist/urls.js.map +1 -1
  247. package/package.json +1 -1
  248. package/dist/components/admin/page-review.d.ts +0 -13
  249. package/dist/components/admin/page-review.js +0 -225
  250. package/dist/components/admin/page-review.js.map +0 -1
  251. package/dist/react/page-review.d.ts +0 -14
  252. package/dist/react/page-review.js +0 -37
  253. package/dist/react/page-review.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"media-folder-editor.js","names":[],"sources":["../../src/components/media-folder-editor.tsx"],"sourcesContent":["import {\n Alert02Icon,\n CropIcon,\n Delete02Icon,\n Edit02Icon,\n File01Icon,\n Image01Icon,\n ImageAdd01Icon,\n Loading03Icon,\n MusicNote01Icon,\n Refresh01Icon,\n RepeatIcon,\n Video01Icon,\n} from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon, type IconSvgElement } from \"@hugeicons/react\";\nimport { itemKey } from \"../client/media/ref.js\";\nimport { cn } from \"cn\";\nimport { useEffect, useImperativeHandle, useMemo, useRef, useState, type DragEvent, type ReactNode, type Ref } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport type { AspectRatio } from \"../client/aspect.js\";\nimport { failureError } from \"../client/errors.js\";\nimport { isAudioType, isImageType, isSubtitleType, isVideoType } from \"../client/gallery.js\";\nimport type { FileInfo, RefBody, UploadRule } from \"../client/generated/wire.js\";\nimport { stem } from \"../client/media/client.js\";\nimport type { QueueItem } from \"../client/media/queue.js\";\nimport { acceptOf, ratioLabel } from \"../client/media/rules.js\";\nimport { isProcessing } from \"../client/media/windows.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { megabytes, type Translator } from \"../i18n/messages.js\";\nimport { useEditorCrop } from \"../react/crop.js\";\nimport { nameIn, thumbnailOf, useMediaFolder, type FolderGroup, type MediaFolderOptions, type UseMediaFolder } from \"../react/folder.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport { Alert, AlertDescription, AlertTitle } from \"#ckui/ui/alert\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Progress } from \"#ckui/ui/progress\";\nimport { EncodeProgress } from \"./encode-progress.js\";\nimport { ImageCropDialog } from \"./image-crop-dialog.js\";\nimport { progressLabel, progressValue } from \"./progress.js\";\nimport { SortableList } from \"./sortable-list.js\";\n\nexport interface MediaFolderEditorHandle {\n /** Stops every upload and empties the queue (before deleting a draft). */\n discard: () => void;\n /** Commits the uploaded files (commit=\"manual\"). */\n commit: () => Promise<FileInfo[]>;\n /** The folder's state and updates. */\n folder: UseMediaFolder;\n}\n\nexport interface MediaFolderEditorViewProps {\n ref?: Ref<MediaFolderEditorHandle>;\n /** Heading; default \"Media\". */\n label?: ReactNode;\n /** Uploaded page images may be arranged as thumbnail tiles. Other groups remain lists. */\n layout?: \"list\" | \"grid\";\n /** Accessible label of the file inputs. */\n inputLabel?: string;\n /** Beside \"Add files\" in the header, e.g. a ZIP import. */\n toolbar?: ReactNode;\n /** Extra actions on each upload, beside crop, rename, replace and remove. */\n rowActions?: (file: FileInfo) => ReactNode;\n /** Below the lists, e.g. what readers without access see. */\n footer?: ReactNode;\n /** Shapes offered when cropping an image whose path has no preset shape; \"\" is the original's. */\n aspects?: readonly AspectRatio[];\n /** Asked before removing selected uploads; default the browser's confirm; false skips it. */\n confirmRemove?: ((count: number) => boolean | Promise<boolean>) | false;\n disabled?: boolean;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Either the item, and the editor opens its folder with the options; or a\n * folder the host opened (`folder={useMediaFolder(ref, options)}`), whose\n * state the host reads and renders with.\n */\nexport type MediaFolderEditorProps = MediaFolderEditorViewProps &\n (\n | ({\n /** The item whose folder this edits. */\n item: RefBody;\n folder?: never;\n } & MediaFolderOptions)\n | ({\n /** The host's folder (useMediaFolder); its ref may be null until the item exists. */\n folder: UseMediaFolder;\n item?: never;\n } & { [K in keyof MediaFolderOptions]?: never })\n );\n\nconst ASPECTS: readonly AspectRatio[] = [\"\", \"1:1\", \"4:5\", \"16:9\"];\n\ntype Kind = \"image\" | \"video\" | \"audio\" | \"subtitle\" | \"file\";\n\nfunction kindOf(type: string | undefined): Kind {\n if (isImageType(type)) return \"image\";\n if (isVideoType(type)) return \"video\";\n if (isAudioType(type)) return \"audio\";\n if (isSubtitleType(type)) return \"subtitle\";\n return \"file\";\n}\n\nconst ICONS: Record<Kind, IconSvgElement> = { image: Image01Icon, video: Video01Icon, audio: MusicNote01Icon, subtitle: File01Icon, file: File01Icon };\n\n/** What a rule takes: one kind when every type is of it, else files. */\nfunction ruleKind(rule: UploadRule | undefined): Kind {\n const kinds = new Set((rule?.types ?? []).map(kindOf));\n return kinds.size === 1 ? [...kinds][0]! : \"file\";\n}\n\n/** The rules as a sentence for the drop zone: sizes, caps and video shapes. */\nexport function describeRules(t: Translator[\"t\"], rules: readonly UploadRule[]): string {\n const parts: string[] = [];\n for (const r of rules) {\n if (!r.types.length) continue;\n const what = t(`folder.kinds.${ruleKind(r)}`);\n const size = r.max_bytes > 0 ? t(\"folder.limitSize\", { what, size: megabytes(r.max_bytes) }) : what;\n parts.push(r.max ? `${size}, ${t(\"folder.limitMax\", { max: r.max })}` : size);\n if (r.min_aspect && r.max_aspect) parts.push(t(\"folder.limitAspect\", { min: ratioLabel(r.min_aspect), max: ratioLabel(r.max_aspect) }));\n }\n return parts.join(\" · \");\n}\n\n/**\n * An item's folder for its editors: drop or pick files (screened against the\n * kind's upload rules), a queue with progress, retry and remove, and each\n * upload path's uploads as a sortable list with thumbnail, name, edited\n * badge, encode progress and failures; crop, rename, replace and bulk\n * remove. commit=\"manual\" adds the queue with \"Add N\"; \"auto\" commits as\n * files finish (a draft; discard() through the ref).\n */\nexport function MediaFolderEditor(p: MediaFolderEditorProps) {\n // Editor state (selection, crop, rename) belongs to one item.\n if (p.folder) {\n const { folder, ...view } = p;\n return <FolderView key={folder.ref ? itemKey(folder.ref) : \"\"} folder={folder} {...view} />;\n }\n // The queue belongs to one item: another item gets a fresh editor.\n return <OwnFolder key={itemKey(p.item)} {...p} />;\n}\n\nfunction OwnFolder(p: MediaFolderEditorViewProps & MediaFolderOptions & { item: RefBody }) {\n const { item, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects, confirmRemove, disabled, className, appearance, ...options } = p;\n const folder = useMediaFolder(item, options);\n return <FolderView {...{ folder, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects, confirmRemove, disabled, className, appearance }} />;\n}\n\nconst NO_ITEM: RefBody = { kind: \"\", id: \"\" };\n\nfunction FolderView(p: MediaFolderEditorViewProps & { folder: UseMediaFolder }) {\n const { folder, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects = ASPECTS, confirmRemove, disabled, className, appearance } = p;\n const { t, error: errorText } = useMessages();\n const { groups, queue, read, options } = folder;\n useImperativeHandle(ref, () => ({ discard: folder.discard, commit: folder.commit, folder }), [folder]);\n const auto = options.commit === \"auto\";\n const rules = groups.flatMap((g) => (g.rule ? [g.rule] : []));\n const accept = acceptOf(rules);\n const count = folder.uploads.length + queue.items.length + folder.waiting.length + folder.pending.length;\n const empty = count === 0;\n const off = !!disabled;\n\n const [selected, setSelected] = useState<ReadonlySet<string>>(new Set());\n useEffect(() => {\n const paths = new Set(folder.uploads.map((f) => f.path));\n setSelected((s) => ([...s].every((x) => paths.has(x)) ? s : new Set([...s].filter((x) => paths.has(x)))));\n }, [folder.uploads]);\n const [cropping, setCropping] = useState<string | null>(null);\n const crop = useEditorCrop(folder.ref ?? NO_ITEM, cropping, { client: options.client, onError: options.onError, onSaved: () => setCropping(null) });\n const cropRule = cropping ? groups.find((g) => g.files.some((f) => f.path === cropping))?.rule : undefined;\n const [renaming, setRenaming] = useState<string | null>(null);\n const replaceInput = useRef<HTMLInputElement>(null);\n const [replacing, setReplacing] = useState<string | null>(null);\n const [over, setOver] = useState(false);\n\n const drop = {\n onDragOver: (e: DragEvent) => {\n if (off || !e.dataTransfer.types.includes(\"Files\")) return;\n e.preventDefault();\n setOver(true);\n },\n onDragLeave: (e: DragEvent) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setOver(false);\n },\n onDrop: (e: DragEvent) => {\n if (off || !e.dataTransfer.files.length) return;\n e.preventDefault();\n setOver(false);\n folder.add(e.dataTransfer.files);\n },\n };\n\n const removeSelected = async () => {\n const paths = [...selected];\n const ok = confirmRemove === false ? true : confirmRemove ? await confirmRemove(paths.length) : globalThis.confirm?.(t(\"folder.confirmRemove\", { count: paths.length })) ?? true;\n if (!ok) return;\n await folder.remove(paths).then(() => setSelected(new Set()), () => {});\n };\n\n const uploaded = queue.items.filter((i) => i.status === \"uploaded\").length + folder.pending.length;\n const picker = (big: boolean) => (\n <label\n className={cn(\n big\n ? \"flex cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border px-4 py-8 text-center text-sm text-muted-foreground transition-colors hover:border-primary hover:bg-primary/5\"\n : \"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-sm font-medium transition-colors hover:bg-muted focus-within:ring-3 focus-within:ring-ring/50\",\n big && over && \"border-primary bg-primary/5\",\n off && \"pointer-events-none opacity-50\",\n )}\n data-ckui={big ? \"folder-drop\" : \"folder-add\"}\n >\n <HugeiconsIcon icon={ImageAdd01Icon} strokeWidth={1.75} className={big ? \"size-7\" : \"size-4\"} />\n {big ? <strong className=\"font-medium text-foreground\">{t(\"folder.drop\")}</strong> : t(\"folder.add\")}\n {big && rules.length > 0 && <span className=\"text-xs\">{describeRules(t, rules)}</span>}\n <input\n type=\"file\"\n multiple\n accept={accept}\n className=\"sr-only\"\n disabled={off}\n data-ckui=\"file\"\n aria-label={inputLabel}\n onChange={(e) => {\n folder.add([...(e.target.files ?? [])]);\n e.target.value = \"\";\n }}\n />\n </label>\n );\n\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-3\", className)} data-ckui=\"media-folder\" data-over={over ? \"\" : undefined} {...drop}>\n <div className=\"flex flex-wrap items-center justify-between gap-2\" data-ckui=\"folder-header\">\n <h3 className=\"text-sm font-semibold\">{label ?? t(\"folder.label\")}</h3>\n <div className=\"flex flex-wrap items-center gap-2\">\n {toolbar}\n {!empty && picker(false)}\n </div>\n </div>\n {empty && (read.read || !folder.ref) && picker(true)}\n {empty && !read.read && read.loading && (\n <div className=\"flex justify-center py-6 text-muted-foreground\" data-ckui=\"folder-loading\">\n <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"size-5 motion-safe:animate-spin\" />\n </div>\n )}\n\n {folder.refused.length > 0 && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-refused\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertDescription>\n <ul className=\"grid gap-0.5\">\n {folder.refused.map((r, i) => (\n <li key={i}>\n <span className=\"font-medium\">{r.file.name}</span>: {errorText(r.error)}\n </li>\n ))}\n </ul>\n <Button variant=\"outline\" size=\"xs\" className=\"mt-1 w-fit\" onClick={folder.dismiss}>\n {t(\"folder.dismiss\")}\n </Button>\n </AlertDescription>\n </Alert>\n )}\n {queue.blocked && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-paused\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertTitle>{t(\"folder.paused\")}</AlertTitle>\n <AlertDescription>\n {errorText(queue.blocked)}\n <Button variant=\"outline\" size=\"xs\" className=\"mt-1 w-fit\" onClick={() => queue.start()}>\n {t(\"folder.resume\")}\n </Button>\n </AlertDescription>\n </Alert>\n )}\n {folder.error && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-error\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertDescription>{errorText(folder.error)}</AlertDescription>\n </Alert>\n )}\n\n {selected.size > 0 && (\n <div className=\"flex flex-wrap items-center gap-2 rounded-md bg-muted px-3 py-1.5 text-sm\" data-ckui=\"folder-selection\">\n <span className=\"tabular-nums\">{t(\"folder.selected\", { count: selected.size })}</span>\n <Button variant=\"destructive\" size=\"xs\" disabled={off || folder.updating} onClick={() => void removeSelected()}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n {t(\"folder.removeSelected\")}\n </Button>\n <Button variant=\"ghost\" size=\"xs\" onClick={() => setSelected(new Set())}>\n {t(\"folder.clearSelection\")}\n </Button>\n </div>\n )}\n\n {groups.map((g) =>\n g.files.length ? (\n <Group\n key={g.path}\n group={g}\n layout={layout === \"grid\" && g.rule?.page ? \"grid\" : \"list\"}\n titled={groups.length > 1}\n folder={folder}\n disabled={off}\n selected={selected}\n onSelect={(path, on) => setSelected((s) => (on ? new Set([...s, path]) : new Set([...s].filter((x) => x !== path))))}\n renaming={renaming}\n onRename={setRenaming}\n onCrop={setCropping}\n onReplace={(path) => {\n setReplacing(path);\n replaceInput.current?.click();\n }}\n rowActions={rowActions}\n />\n ) : null,\n )}\n\n {folder.waiting.length > 0 && (\n <ul className=\"grid\" aria-label={t(\"folder.label\")}>\n {folder.waiting.map((f, i) => (\n <li key={i} className=\"flex min-h-11 items-center gap-2 px-1\" data-ckui=\"queue-row\" data-status=\"waiting\">\n <Thumb kind={kindOf(f.type)} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\">{f.name}</span>\n <span className=\"text-xs text-muted-foreground\" data-ckui=\"queue-status\">\n {t(\"folder.queued\")}\n </span>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n {folder.pending.length > 0 && (\n <ul className=\"grid\" aria-label={t(\"folder.label\")} data-ckui=\"folder-pending\">\n {folder.pending.map((f) => (\n <PendingRow key={f.path} file={f} folder={folder} auto={auto} disabled={off} />\n ))}\n </ul>\n )}\n\n {queue.items.length > 0 && (\n <SortableList\n items={queue.items}\n id={(i) => i.id}\n name={(i) => i.file.name}\n disabled={auto || off}\n label={t(\"folder.label\")}\n onMove={(from, to) => queue.move(queue.items[from]!.id, to)}\n row={(i) => ({ className: \"flex min-h-11 items-center gap-2 px-1\", \"data-ckui\": \"queue-row\", \"data-status\": i.status })}\n >\n {(i, handle) => <QueueRow item={i} handle={auto ? null : handle} auto={auto} folder={folder} />}\n </SortableList>\n )}\n\n {((!auto && uploaded > 0) || (auto && folder.error && uploaded > 0)) && (\n <Button className=\"w-fit\" disabled={off || (queue.items.length > 0 && !queue.ready) || folder.committing} onClick={() => void folder.commit().catch(() => {})} data-ckui=\"folder-commit\">\n {folder.committing && <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"motion-safe:animate-spin\" />}\n {auto ? t(\"folder.commitAgain\") : t(\"folder.commit\", { count: queue.items.filter((i) => i.status !== \"committed\").length + folder.pending.length })}\n </Button>\n )}\n {footer}\n\n <input\n ref={replaceInput}\n type=\"file\"\n accept={accept}\n className=\"sr-only\"\n tabIndex={-1}\n aria-hidden\n onChange={(e) => {\n const f = e.target.files?.[0];\n e.target.value = \"\";\n if (f && replacing) void folder.replace(replacing, f).catch(() => {});\n setReplacing(null);\n }}\n />\n <ImageCropDialog\n open={!!cropping}\n onOpenChange={(o) => !o && crop.status !== \"saving\" && setCropping(null)}\n source={\"source\" in crop ? (crop.source ?? null) : null}\n aspect={cropRule?.aspect ?? \"\"}\n aspects={cropRule?.aspect ? undefined : aspects}\n initialEdit={\"edit\" in crop ? crop.edit : null}\n minWidth={cropRule?.min_width}\n title={t(\"folder.crop\")}\n busy={crop.status === \"saving\"}\n error={crop.status === \"error\" ? errorText(crop.error) : undefined}\n onConfirm={(edit) => void crop.save(edit)}\n />\n </ContentKitUiRoot>\n );\n}\n\nfunction Group({\n group,\n layout,\n titled,\n folder,\n disabled,\n selected,\n onSelect,\n renaming,\n onRename,\n onCrop,\n onReplace,\n rowActions,\n}: {\n group: FolderGroup;\n layout: \"list\" | \"grid\";\n titled: boolean;\n folder: UseMediaFolder;\n disabled: boolean;\n selected: ReadonlySet<string>;\n onSelect: (path: string, on: boolean) => void;\n renaming: string | null;\n onRename: (path: string | null) => void;\n onCrop: (path: string) => void;\n onReplace: (path: string) => void;\n rowActions?: (file: FileInfo) => ReactNode;\n}) {\n const { t } = useMessages();\n const kind = ruleKind(group.rule);\n const title = t(`folder.kinds.${kind}`);\n const max = group.rule?.max;\n return (\n <section className=\"grid gap-1\" data-ckui=\"folder-group\" data-path={group.path}>\n {titled && (\n <h4 className=\"px-1 text-xs font-medium text-muted-foreground tabular-nums\">\n {title} · {max ? `${group.files.length} / ${max}` : group.files.length}\n </h4>\n )}\n <SortableList\n layout={layout}\n className={layout === \"grid\" ? \"grid-cols-[repeat(auto-fill,minmax(12rem,1fr))]\" : undefined}\n items={group.files}\n id={(f) => f.path}\n name={(f) => nameIn(group, f.path)}\n disabled={disabled || folder.updating}\n label={title}\n onMove={(from, to) => void folder.move(group.files[from]!.path, to).catch(() => {})}\n row={(f) => ({ className: layout === \"grid\" ? \"grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-start gap-2 rounded-lg border border-border bg-background p-2\" : \"flex min-h-12 items-center gap-2 px-1\", \"data-ckui\": \"upload-row\", \"data-path\": f.path })}\n >\n {(f, handle) => (\n <UploadRow\n file={f}\n grid={layout === \"grid\"}\n group={group}\n handle={handle}\n folder={folder}\n disabled={disabled}\n selected={selected.has(f.path)}\n onSelect={(on) => onSelect(f.path, on)}\n renaming={renaming === f.path}\n onRename={onRename}\n onCrop={onCrop}\n onReplace={onReplace}\n actions={rowActions?.(f)}\n />\n )}\n </SortableList>\n </section>\n );\n}\n\nfunction Thumb({ kind, url, busy, grid, aspect }: { kind: Kind; url?: string; busy?: boolean; grid?: boolean; aspect?: number }) {\n return (\n <span className={cn(\"relative flex shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted text-muted-foreground\",grid?\"col-span-2 w-full\":\"size-10\")} style={grid?{aspectRatio:aspect??0.75}:undefined} data-ckui=\"thumb\">\n {url ? <img src={url} alt=\"\" loading=\"lazy\" decoding=\"async\" className=\"size-full object-cover\" /> : <HugeiconsIcon icon={ICONS[kind]} strokeWidth={1.75} className=\"size-4.5\" />}\n {busy && !url && <span aria-hidden className=\"absolute inset-1.5 rounded-full border-2 border-current/25 border-t-current motion-safe:animate-spin\" />}\n </span>\n );\n}\n\nfunction UploadRow({\n file: f,\n grid,\n group,\n handle,\n folder,\n disabled,\n selected,\n onSelect,\n renaming,\n onRename,\n onCrop,\n onReplace,\n actions,\n}: {\n file: FileInfo;\n grid?: boolean;\n group: FolderGroup;\n handle: ReactNode;\n folder: UseMediaFolder;\n disabled: boolean;\n selected: boolean;\n onSelect: (on: boolean) => void;\n renaming: boolean;\n onRename: (path: string | null) => void;\n onCrop: (path: string) => void;\n onReplace: (path: string) => void;\n actions?: ReactNode;\n}) {\n const { t, error: errorText } = useMessages();\n const kind = kindOf(f.type);\n const name = nameIn(group, f.path);\n const busy = isProcessing(f);\n const thumb = useMemo(() => thumbnailOf(folder.read.read, f), [folder.read.read, f]);\n const locked = disabled || folder.updating;\n const failure = f.failed ? errorText(failureError(f.failed)) : undefined;\n return (\n <>\n {handle}\n <input\n type=\"checkbox\"\n className=\"size-4 shrink-0 accent-primary\"\n checked={selected}\n disabled={disabled}\n aria-label={t(\"folder.select\", { name })}\n onChange={(e) => onSelect(e.target.checked)}\n />\n <Thumb kind={kind} url={thumb?.url} busy={busy} grid={grid} aspect={thumb?.w&&thumb.h?thumb.w/thumb.h:undefined} />\n <div className={cn(\"grid min-w-0 flex-1 gap-1\",grid&&\"col-span-2\")}>\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5\">\n {renaming ? (\n <RenameInput name={stem(name)} label={t(\"folder.renameLabel\", { name })} onDone={(to) => (to === null ? onRename(null) : folder.rename(f.path, to).then(() => onRename(null)))} />\n ) : (\n <span className=\"max-w-full truncate text-sm\" title={f.path} data-ckui=\"upload-name\">\n {name}\n </span>\n )}\n {f.edit && (\n <span className=\"shrink-0 rounded-sm border border-border px-1.5 text-[11px] text-muted-foreground\" data-ckui=\"edited\">\n {t(\"folder.edited\")}\n </span>\n )}\n {failure && (\n <span className=\"shrink-0 rounded-sm bg-destructive/10 px-1.5 text-[11px] font-medium text-destructive\" title={failure} data-ckui=\"failed\">\n {kind === \"video\" ? t(\"folder.failedVideo\") : t(\"folder.failed\")}\n </span>\n )}\n </div>\n {failure && <p className=\"text-xs text-destructive\">{failure}</p>}\n {busy && kind === \"video\" && <EncodeProgress progress={f.progress} className=\"max-w-sm text-xs\" />}\n {busy && kind !== \"video\" && <span className=\"text-xs text-muted-foreground\">{t(\"folder.processing\")}</span>}\n </div>\n <span className={cn(\"flex shrink-0 flex-wrap items-center gap-0.5\",grid&&\"col-span-2 justify-end\")} data-ckui=\"upload-actions\">\n {actions}\n {kind === \"image\" && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"folder.crop\")} title={t(\"folder.crop\")} disabled={locked || !!f.staged || !f.size} onClick={() => onCrop(f.path)}>\n <HugeiconsIcon icon={CropIcon} strokeWidth={2} />\n </Button>\n )}\n {!group.rule?.named && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.rename\")} title={t(\"common.rename\")} disabled={locked} onClick={() => onRename(f.path)}>\n <HugeiconsIcon icon={Edit02Icon} strokeWidth={2} />\n </Button>\n )}\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.replace\")} title={t(\"common.replace\")} disabled={locked} onClick={() => onReplace(f.path)}>\n <HugeiconsIcon icon={RepeatIcon} strokeWidth={2} />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} disabled={locked} onClick={() => void folder.remove([f.path]).catch(() => {})}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </span>\n </>\n );\n}\n\nfunction RenameInput({ name, label, onDone }: { name: string; label: string; onDone: (to: string | null) => unknown }) {\n const [value, setValue] = useState(name);\n const done = useRef(false);\n const finish = (to: string | null) => {\n if (done.current) return;\n done.current = true;\n Promise.resolve(onDone(to && to.trim() && to.trim() !== name ? to.trim() : null)).catch(() => (done.current = false));\n };\n return (\n <input\n autoFocus\n aria-label={label}\n value={value}\n className=\"h-7 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-3 focus-visible:ring-ring/50\"\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n finish(value);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n finish(null);\n }\n }}\n onBlur={() => finish(value)}\n data-ckui=\"rename\"\n />\n );\n}\n\n/** An upload on the server not yet added: an earlier visit's, kept across reloads. */\nfunction PendingRow({ file: f, folder, auto, disabled }: { file: FileInfo; folder: UseMediaFolder; auto: boolean; disabled: boolean }) {\n const { t, error: errorText } = useMessages();\n const kind = kindOf(f.type);\n const busy = isProcessing(f);\n const thumb = useMemo(() => thumbnailOf(folder.read.read, f), [folder.read.read, f]);\n const label = f.failed\n ? errorText(failureError(f.failed))\n : busy\n ? f.progress && f.progress.phase !== \"queued\"\n ? t(\"folder.processingPercent\", { percent: Math.round(f.progress.percent) })\n : t(\"folder.processing\")\n : auto\n ? t(\"folder.adding\")\n : t(\"folder.notAdded\");\n return (\n <li className=\"flex min-h-11 items-center gap-2 px-1\" data-ckui=\"pending-row\" data-path={f.path}>\n <Thumb kind={kind} url={thumb?.url} busy={busy} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\" title={f.path}>\n {f.path.slice(f.path.lastIndexOf(\"/\") + 1)}\n </span>\n <span className={cn(\"text-xs\", f.failed ? \"text-destructive\" : \"text-muted-foreground\")} data-ckui=\"queue-status\">\n {label}\n </span>\n </div>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} disabled={disabled || folder.updating} onClick={() => void folder.remove([f.path]).catch(() => {})}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </li>\n );\n}\n\nfunction queueLabel(t: Translator[\"t\"], errorText: Translator[\"error\"], i: QueueItem, auto: boolean): string {\n if (i.status === \"failed\") return errorText(i.error);\n if (i.status === \"uploading\") return progressLabel(t, i.progress);\n if (i.status === \"uploaded\") {\n const p = i.processing;\n if (p?.failed) return errorText(failureError(p.failed));\n if (i.unattached && !i.processed) return p?.progress && p.progress.phase !== \"queued\" ? t(\"folder.processingPercent\", { percent: Math.round(p.progress.percent) }) : t(\"folder.processing\");\n return auto ? t(\"folder.adding\") : t(\"folder.uploaded\");\n }\n return i.status === \"committed\" ? t(\"folder.adding\") : t(\"folder.queued\");\n}\n\nfunction QueueRow({ item: i, handle, auto, folder }: { item: QueueItem; handle: ReactNode; auto: boolean; folder: UseMediaFolder }) {\n const { t, error: errorText } = useMessages();\n const { queue } = folder;\n const kind = kindOf(i.file.type);\n const label = queueLabel(t, errorText, i, auto);\n const value = i.status === \"uploading\" ? progressValue(i.progress) : i.unattached && !i.processed && i.processing?.progress ? i.processing.progress.percent : null;\n return (\n <>\n {handle}\n <Thumb kind={kind} busy={i.status === \"uploading\" || (!!i.unattached && !i.processed)} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\" title={i.path}>\n {i.file.name}\n </span>\n {value !== null && <Progress value={value} aria-label={label} className=\"max-w-sm\" />}\n <span className={cn(\"text-xs\", i.status === \"failed\" ? \"text-destructive\" : \"text-muted-foreground\")} data-ckui=\"queue-status\">\n {label}\n </span>\n </div>\n <span className=\"flex shrink-0 items-center gap-0.5\">\n {i.status === \"failed\" && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.retry\")} title={t(\"common.retry\")} onClick={() => queue.retry(i.id)}>\n <HugeiconsIcon icon={Refresh01Icon} strokeWidth={2} />\n </Button>\n )}\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} onClick={() => queue.remove(i.id)}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </span>\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"media-folder-editor.js","names":[],"sources":["../../src/components/media-folder-editor.tsx"],"sourcesContent":["import {\n Alert02Icon,\n Cancel01Icon,\n CropIcon,\n Delete02Icon,\n Edit02Icon,\n File01Icon,\n Image01Icon,\n ImageAdd01Icon,\n Loading03Icon,\n MusicNote01Icon,\n Refresh01Icon,\n RepeatIcon,\n Video01Icon,\n} from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon, type IconSvgElement } from \"@hugeicons/react\";\nimport { itemKey } from \"../client/media/ref.js\";\nimport { cn } from \"cn\";\nimport { useEffect, useImperativeHandle, useMemo, useRef, useState, type DragEvent, type ReactNode, type Ref } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport type { AspectRatio } from \"../client/aspect.js\";\nimport { failureError } from \"../client/errors.js\";\nimport { isAudioType, isImageType, isSubtitleType, isVideoType } from \"../client/gallery.js\";\nimport type { FileInfo, RefBody, UploadRule } from \"../client/generated/wire.js\";\nimport { stem } from \"../client/media/client.js\";\nimport type { QueueItem } from \"../client/media/queue.js\";\nimport { acceptOf, ratioLabel, ruleFor } from \"../client/media/rules.js\";\nimport { isProcessing, pageRemoved } from \"../client/media/windows.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { megabytes, type Translator } from \"../i18n/messages.js\";\nimport { useEditorCrop } from \"../react/crop.js\";\nimport { nameIn, thumbnailOf, useMediaFolder, type FolderGroup, type MediaFolderOptions, type UseMediaFolder } from \"../react/folder.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport { Alert, AlertDescription, AlertTitle } from \"#ckui/ui/alert\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Progress } from \"#ckui/ui/progress\";\nimport { EncodeProgress } from \"./encode-progress.js\";\nimport { ImageCropDialog } from \"./image-crop-dialog.js\";\nimport { progressLabel, progressValue } from \"./progress.js\";\nimport { SortableList } from \"./sortable-list.js\";\n\nexport interface MediaFolderEditorHandle {\n /** Stops every upload and empties the queue (before deleting a draft). */\n discard: () => void;\n /** Commits the uploaded files (commit=\"manual\"). */\n commit: () => Promise<FileInfo[]>;\n /** The folder's state and updates. */\n folder: UseMediaFolder;\n}\n\nexport interface MediaFolderEditorViewProps {\n ref?: Ref<MediaFolderEditorHandle>;\n /** Heading; default \"Media\". */\n label?: ReactNode;\n /** Uploaded page images may be arranged as thumbnail tiles. Other groups remain lists. */\n layout?: \"list\" | \"grid\";\n /** Accessible label of the file inputs. */\n inputLabel?: string;\n /** Beside \"Add files\" in the header, e.g. a ZIP import. */\n toolbar?: ReactNode;\n /** Extra actions on each upload, beside crop, rename, replace and remove. */\n rowActions?: (file: FileInfo) => ReactNode;\n /** Below the lists, e.g. what readers without access see. */\n footer?: ReactNode;\n /** Shapes offered when cropping an image whose path has no preset shape; \"\" is the original's. */\n aspects?: readonly AspectRatio[];\n /** The page tile chosen in a grid (e.g. to set a thumbnail from); clicking a tile reports it, again clears it. */\n selectedPage?: string | null;\n onSelectPage?: (file: FileInfo | null) => void;\n /** Asked before removing selected uploads; default the browser's confirm; false skips it. */\n confirmRemove?: ((count: number) => boolean | Promise<boolean>) | false;\n disabled?: boolean;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Either the item, and the editor opens its folder with the options; or a\n * folder the host opened (`folder={useMediaFolder(ref, options)}`), whose\n * state the host reads and renders with.\n */\nexport type MediaFolderEditorProps = MediaFolderEditorViewProps &\n (\n | ({\n /** The item whose folder this edits. */\n item: RefBody;\n folder?: never;\n } & MediaFolderOptions)\n | ({\n /** The host's folder (useMediaFolder); its ref may be null until the item exists. */\n folder: UseMediaFolder;\n item?: never;\n } & { [K in keyof MediaFolderOptions]?: never })\n );\n\nconst ASPECTS: readonly AspectRatio[] = [\"\", \"1:1\", \"4:5\", \"16:9\"];\n\ntype Kind = \"image\" | \"video\" | \"audio\" | \"subtitle\" | \"file\";\n\nfunction kindOf(type: string | undefined): Kind {\n if (isImageType(type)) return \"image\";\n if (isVideoType(type)) return \"video\";\n if (isAudioType(type)) return \"audio\";\n if (isSubtitleType(type)) return \"subtitle\";\n return \"file\";\n}\n\nconst ICONS: Record<Kind, IconSvgElement> = { image: Image01Icon, video: Video01Icon, audio: MusicNote01Icon, subtitle: File01Icon, file: File01Icon };\n\n/** What a rule takes: one kind when every type is of it, else files. */\nfunction ruleKind(rule: UploadRule | undefined): Kind {\n const kinds = new Set((rule?.types ?? []).map(kindOf));\n return kinds.size === 1 ? [...kinds][0]! : \"file\";\n}\n\n/** The rules as a sentence for the drop zone: sizes, caps and video shapes. */\nexport function describeRules(t: Translator[\"t\"], rules: readonly UploadRule[]): string {\n const parts: string[] = [];\n for (const r of rules) {\n if (!r.types.length) continue;\n const what = t(`folder.kinds.${ruleKind(r)}`);\n const size = r.max_bytes > 0 ? t(\"folder.limitSize\", { what, size: megabytes(r.max_bytes) }) : what;\n parts.push(r.max ? `${size}, ${t(\"folder.limitMax\", { max: r.max })}` : size);\n if (r.min_aspect && r.max_aspect) parts.push(t(\"folder.limitAspect\", { min: ratioLabel(r.min_aspect), max: ratioLabel(r.max_aspect) }));\n }\n return parts.join(\" · \");\n}\n\n/**\n * An item's folder for its editors: drop or pick files (screened against the\n * kind's upload rules), a queue with progress, retry and remove, and each\n * upload path's uploads as a sortable list with thumbnail, name, edited\n * badge, encode progress and failures; crop, rename, replace and bulk\n * remove. commit=\"manual\" adds the queue with \"Add N\"; \"auto\" commits as\n * files finish (a draft; discard() through the ref).\n */\nexport function MediaFolderEditor(p: MediaFolderEditorProps) {\n // Editor state (selection, crop, rename) belongs to one item.\n if (p.folder) {\n const { folder, ...view } = p;\n return <FolderView key={folder.ref ? itemKey(folder.ref) : \"\"} folder={folder} {...view} />;\n }\n // The queue belongs to one item: another item gets a fresh editor.\n return <OwnFolder key={itemKey(p.item)} {...p} />;\n}\n\nfunction OwnFolder(p: MediaFolderEditorViewProps & MediaFolderOptions & { item: RefBody }) {\n const { item, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects, confirmRemove, disabled, className, appearance, selectedPage, onSelectPage, ...options } = p;\n const folder = useMediaFolder(item, options);\n return <FolderView {...{ folder, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects, confirmRemove, disabled, className, appearance, selectedPage, onSelectPage }} />;\n}\n\nconst NO_ITEM: RefBody = { kind: \"\", id: \"\" };\n\nfunction FolderView(p: MediaFolderEditorViewProps & { folder: UseMediaFolder }) {\n const { folder, ref, label, layout, inputLabel, toolbar, rowActions, footer, aspects = ASPECTS, confirmRemove, disabled, className, appearance, selectedPage, onSelectPage } = p;\n const { t, error: errorText } = useMessages();\n const { groups, queue, read, options } = folder;\n useImperativeHandle(ref, () => ({ discard: folder.discard, commit: folder.commit, folder }), [folder]);\n const auto = options.commit === \"auto\";\n const rules = groups.flatMap((g) => (g.rule ? [g.rule] : []));\n const accept = acceptOf(rules);\n const count = folder.uploads.length + queue.items.length + folder.waiting.length + folder.pending.length;\n const empty = count === 0;\n const off = !!disabled;\n\n const [selected, setSelected] = useState<ReadonlySet<string>>(new Set());\n useEffect(() => {\n const paths = new Set(folder.uploads.map((f) => f.path));\n setSelected((s) => ([...s].every((x) => paths.has(x)) ? s : new Set([...s].filter((x) => paths.has(x)))));\n }, [folder.uploads]);\n const [cropping, setCropping] = useState<string | null>(null);\n const crop = useEditorCrop(folder.ref ?? NO_ITEM, cropping, { client: options.client, onError: options.onError, onSaved: () => setCropping(null) });\n const cropRule = cropping ? groups.find((g) => g.files.some((f) => f.path === cropping))?.rule : undefined;\n const [renaming, setRenaming] = useState<string | null>(null);\n const replaceInput = useRef<HTMLInputElement>(null);\n const [replacing, setReplacing] = useState<string | null>(null);\n const [over, setOver] = useState(false);\n\n const drop = {\n onDragOver: (e: DragEvent) => {\n if (off || !e.dataTransfer.types.includes(\"Files\")) return;\n e.preventDefault();\n setOver(true);\n },\n onDragLeave: (e: DragEvent) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setOver(false);\n },\n onDrop: (e: DragEvent) => {\n if (off || !e.dataTransfer.files.length) return;\n e.preventDefault();\n setOver(false);\n folder.add(e.dataTransfer.files);\n },\n };\n\n const removeSelected = async () => {\n const paths = [...selected];\n const ok = confirmRemove === false ? true : confirmRemove ? await confirmRemove(paths.length) : globalThis.confirm?.(t(\"folder.confirmRemove\", { count: paths.length })) ?? true;\n if (!ok) return;\n await folder.remove(paths).then(() => setSelected(new Set()), () => {});\n };\n\n const uploaded = queue.items.filter((i) => i.status === \"uploaded\").length + folder.pending.length;\n // Page uploads in flight join the page grid as tiles; the rest stay listed.\n const pageGroup = layout === \"grid\" ? groups.find((g) => g.rule?.page) : undefined;\n const inPages = (path: string) => !!pageGroup && ruleFor(rules, path)?.path === pageGroup.rule!.path;\n const pageQueue = queue.items.filter((i) => inPages(i.path));\n const otherQueue = queue.items.filter((i) => !inPages(i.path));\n const pagePending = folder.pending.filter((f) => inPages(f.path));\n const otherPending = folder.pending.filter((f) => !inPages(f.path));\n const pageWaiting = pageGroup ? folder.waiting.filter((f) => isImageType(f.type)) : [];\n const otherWaiting = pageGroup ? folder.waiting.filter((f) => !isImageType(f.type)) : folder.waiting;\n const picker = (big: boolean) => (\n <label\n className={cn(\n big\n ? \"flex cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border px-4 py-8 text-center text-sm text-muted-foreground transition-colors hover:border-primary hover:bg-primary/5\"\n : \"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-sm font-medium transition-colors hover:bg-muted focus-within:ring-3 focus-within:ring-ring/50\",\n big && over && \"border-primary bg-primary/5\",\n off && \"pointer-events-none opacity-50\",\n )}\n data-ckui={big ? \"folder-drop\" : \"folder-add\"}\n >\n <HugeiconsIcon icon={ImageAdd01Icon} strokeWidth={1.75} className={big ? \"size-7\" : \"size-4\"} />\n {big ? <strong className=\"font-medium text-foreground\">{t(\"folder.drop\")}</strong> : t(\"folder.add\")}\n {big && rules.length > 0 && <span className=\"text-xs\">{describeRules(t, rules)}</span>}\n <input\n type=\"file\"\n multiple\n accept={accept}\n className=\"sr-only\"\n disabled={off}\n data-ckui=\"file\"\n aria-label={inputLabel}\n onChange={(e) => {\n folder.add([...(e.target.files ?? [])]);\n e.target.value = \"\";\n }}\n />\n </label>\n );\n\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-3\", className)} data-ckui=\"media-folder\" data-over={over ? \"\" : undefined} {...drop}>\n <div className=\"flex flex-wrap items-center justify-between gap-2\" data-ckui=\"folder-header\">\n {label !== false && <h3 className=\"text-sm font-semibold\">{label ?? t(\"folder.label\")}</h3>}\n <div className=\"flex flex-wrap items-center gap-2\">\n {toolbar}\n {!empty && picker(false)}\n </div>\n </div>\n {empty && (read.read || !folder.ref) && picker(true)}\n {empty && !read.read && read.loading && (\n <div className=\"flex justify-center py-6 text-muted-foreground\" data-ckui=\"folder-loading\">\n <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"size-5 motion-safe:animate-spin\" />\n </div>\n )}\n\n {folder.refused.length > 0 && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-refused\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertDescription>\n <ul className=\"grid gap-0.5\">\n {folder.refused.map((r, i) => (\n <li key={i}>\n <span className=\"font-medium\">{r.file.name}</span>: {errorText(r.error)}\n </li>\n ))}\n </ul>\n <Button variant=\"outline\" size=\"xs\" className=\"mt-1 w-fit\" onClick={folder.dismiss}>\n {t(\"folder.dismiss\")}\n </Button>\n </AlertDescription>\n </Alert>\n )}\n {queue.blocked && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-paused\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertTitle>{t(\"folder.paused\")}</AlertTitle>\n <AlertDescription>\n {errorText(queue.blocked)}\n <Button variant=\"outline\" size=\"xs\" className=\"mt-1 w-fit\" onClick={() => queue.start()}>\n {t(\"folder.resume\")}\n </Button>\n </AlertDescription>\n </Alert>\n )}\n {folder.error && (\n <Alert variant=\"destructive\" role=\"alert\" data-ckui=\"folder-error\">\n <HugeiconsIcon icon={Alert02Icon} strokeWidth={2} />\n <AlertDescription>{errorText(folder.error)}</AlertDescription>\n </Alert>\n )}\n\n {selected.size > 0 && (\n <div className=\"flex flex-wrap items-center gap-2 rounded-md bg-muted px-3 py-1.5 text-sm\" data-ckui=\"folder-selection\">\n <span className=\"tabular-nums\">{t(\"folder.selected\", { count: selected.size })}</span>\n <Button variant=\"destructive\" size=\"xs\" disabled={off || folder.updating} onClick={() => void removeSelected()}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n {t(\"folder.removeSelected\")}\n </Button>\n <Button variant=\"ghost\" size=\"xs\" onClick={() => setSelected(new Set())}>\n {t(\"folder.clearSelection\")}\n </Button>\n </div>\n )}\n\n {groups.map((g) =>\n g === pageGroup ? (\n g.files.length + pageQueue.length + pagePending.length + pageWaiting.length > 0 && (\n <PageGrid\n key={g.path}\n group={g}\n folder={folder}\n disabled={off}\n auto={auto}\n selected={selectedPage ?? null}\n onSelect={(f) => onSelectPage?.(f)}\n queued={pageQueue}\n pending={pagePending}\n waiting={pageWaiting}\n />\n )\n ) : g.files.length ? (\n <Group\n key={g.path}\n group={g}\n layout={layout === \"grid\" && g.rule?.page ? \"grid\" : \"list\"}\n titled={groups.length > 1}\n folder={folder}\n disabled={off}\n selected={selected}\n onSelect={(path, on) => setSelected((s) => (on ? new Set([...s, path]) : new Set([...s].filter((x) => x !== path))))}\n renaming={renaming}\n onRename={setRenaming}\n onCrop={setCropping}\n onReplace={(path) => {\n setReplacing(path);\n replaceInput.current?.click();\n }}\n rowActions={rowActions}\n />\n ) : null,\n )}\n\n {otherWaiting.length > 0 && (\n <ul className=\"grid\" aria-label={t(\"folder.label\")}>\n {otherWaiting.map((f, i) => (\n <li key={i} className=\"flex min-h-11 items-center gap-2 px-1\" data-ckui=\"queue-row\" data-status=\"waiting\">\n <Thumb kind={kindOf(f.type)} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\">{f.name}</span>\n <span className=\"text-xs text-muted-foreground\" data-ckui=\"queue-status\">\n {t(\"folder.queued\")}\n </span>\n </div>\n </li>\n ))}\n </ul>\n )}\n\n {otherPending.length > 0 && (\n <ul className=\"grid\" aria-label={t(\"folder.label\")} data-ckui=\"folder-pending\">\n {otherPending.map((f) => (\n <PendingRow key={f.path} file={f} folder={folder} auto={auto} disabled={off} />\n ))}\n </ul>\n )}\n\n {otherQueue.length > 0 && (\n <SortableList\n items={otherQueue}\n id={(i) => i.id}\n name={(i) => i.file.name}\n disabled={auto || off}\n label={t(\"folder.label\")}\n onMove={(from, to) => queue.move(otherQueue[from]!.id, queue.items.indexOf(otherQueue[to]!))}\n row={(i) => ({ className: \"flex min-h-11 items-center gap-2 px-1\", \"data-ckui\": \"queue-row\", \"data-status\": i.status })}\n >\n {(i, handle) => <QueueRow item={i} handle={auto ? null : handle} auto={auto} folder={folder} />}\n </SortableList>\n )}\n\n {((!auto && uploaded > 0) || (auto && folder.error && uploaded > 0)) && (\n <Button className=\"w-fit\" disabled={off || (queue.items.length > 0 && !queue.ready) || folder.committing} onClick={() => void folder.commit().catch(() => {})} data-ckui=\"folder-commit\">\n {folder.committing && <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"motion-safe:animate-spin\" />}\n {auto ? t(\"folder.commitAgain\") : t(\"folder.commit\", { count: queue.items.filter((i) => i.status !== \"committed\").length + folder.pending.length })}\n </Button>\n )}\n {footer}\n\n <input\n ref={replaceInput}\n type=\"file\"\n accept={accept}\n className=\"sr-only\"\n tabIndex={-1}\n aria-hidden\n onChange={(e) => {\n const f = e.target.files?.[0];\n e.target.value = \"\";\n if (f && replacing) void folder.replace(replacing, f).catch(() => {});\n setReplacing(null);\n }}\n />\n <ImageCropDialog\n open={!!cropping}\n onOpenChange={(o) => !o && crop.status !== \"saving\" && setCropping(null)}\n source={\"source\" in crop ? (crop.source ?? null) : null}\n aspect={cropRule?.aspect ?? \"\"}\n aspects={cropRule?.aspect ? undefined : aspects}\n initialEdit={\"edit\" in crop ? crop.edit : null}\n minWidth={cropRule?.min_width}\n title={t(\"folder.crop\")}\n busy={crop.status === \"saving\"}\n error={crop.status === \"error\" ? errorText(crop.error) : undefined}\n onConfirm={(edit) => void crop.save(edit)}\n />\n </ContentKitUiRoot>\n );\n}\n\nfunction Group({\n group,\n layout,\n titled,\n folder,\n disabled,\n selected,\n onSelect,\n renaming,\n onRename,\n onCrop,\n onReplace,\n rowActions,\n}: {\n group: FolderGroup;\n layout: \"list\" | \"grid\";\n titled: boolean;\n folder: UseMediaFolder;\n disabled: boolean;\n selected: ReadonlySet<string>;\n onSelect: (path: string, on: boolean) => void;\n renaming: string | null;\n onRename: (path: string | null) => void;\n onCrop: (path: string) => void;\n onReplace: (path: string) => void;\n rowActions?: (file: FileInfo) => ReactNode;\n}) {\n const { t } = useMessages();\n const kind = ruleKind(group.rule);\n const title = t(`folder.kinds.${kind}`);\n const max = group.rule?.max;\n return (\n <section className=\"grid gap-1\" data-ckui=\"folder-group\" data-path={group.path}>\n {titled && (\n <h4 className=\"px-1 text-xs font-medium text-muted-foreground tabular-nums\">\n {title} · {max ? `${group.files.length} / ${max}` : group.files.length}\n </h4>\n )}\n <SortableList\n layout={layout}\n className={layout === \"grid\" ? \"grid-cols-[repeat(auto-fill,minmax(12rem,1fr))]\" : undefined}\n items={group.files}\n id={(f) => f.path}\n name={(f) => nameIn(group, f.path)}\n disabled={disabled || folder.updating}\n label={title}\n onMove={(from, to) => void folder.move(group.files[from]!.path, to).catch(() => {})}\n row={(f) => ({ className: layout === \"grid\" ? \"grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-start gap-2 rounded-lg border border-border bg-background p-2\" : \"flex min-h-12 items-center gap-2 px-1\", \"data-ckui\": \"upload-row\", \"data-path\": f.path })}\n >\n {(f, handle) => (\n <UploadRow\n file={f}\n grid={layout === \"grid\"}\n group={group}\n handle={handle}\n folder={folder}\n disabled={disabled}\n selected={selected.has(f.path)}\n onSelect={(on) => onSelect(f.path, on)}\n renaming={renaming === f.path}\n onRename={onRename}\n onCrop={onCrop}\n onReplace={onReplace}\n actions={rowActions?.(f)}\n />\n )}\n </SortableList>\n </section>\n );\n}\n\n/** A page's name from its place: zero-padded to at least two digits, keeping its extension. */\nexport function positionalName(position: number, count: number, path: string): string {\n const dot = path.lastIndexOf(\".\");\n const ext = dot > path.lastIndexOf(\"/\") ? path.slice(dot).toLowerCase() : \"\";\n return String(position).padStart(Math.max(2, String(count).length), \"0\") + ext;\n}\n\nconst TILE = \"group relative grid min-w-0 content-start gap-1 rounded-lg border bg-background p-1.5 outline-none focus-visible:ring-2 focus-visible:ring-ring\";\n\nfunction RemoveTile({ label, disabled, onRemove }: { label: string; disabled?: boolean; onRemove: () => void }) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n className=\"absolute end-2 top-2 inline-flex size-6 items-center justify-center rounded-full bg-background/90 text-muted-foreground opacity-0 shadow-sm transition-opacity hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100 group-focus-within:opacity-100 disabled:hidden\"\n onPointerDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n data-ckui=\"tile-remove\"\n >\n <HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-3.5\" />\n </button>\n );\n}\n\nfunction TileImage({ url, aspect, busy }: { url?: string; aspect?: number; busy?: boolean }) {\n return (\n <span className=\"relative block w-full overflow-hidden rounded-md bg-muted\" style={{ aspectRatio: aspect ?? 0.75 }}>\n {url && <img src={url} alt=\"\" loading=\"lazy\" decoding=\"async\" draggable={false} className={cn(\"size-full object-cover\", busy && \"opacity-70\")} />}\n {busy && !url && <span aria-hidden className=\"absolute inset-[40%] rounded-full border-2 border-current/25 border-t-current text-muted-foreground motion-safe:animate-spin\" />}\n </span>\n );\n}\n\n/**\n * Pages as one grid: committed pages (drag anywhere on a tile to reorder;\n * names follow position) followed by uploads still on their way, shown from\n * their local files. Pages automatic processing removed are left out.\n */\nfunction PageGrid({\n group,\n folder,\n disabled,\n auto,\n selected,\n onSelect,\n queued,\n pending,\n waiting,\n}: {\n group: FolderGroup;\n folder: UseMediaFolder;\n disabled: boolean;\n auto: boolean;\n selected: string | null;\n onSelect: (file: FileInfo | null) => void;\n queued: readonly QueueItem[];\n pending: readonly FileInfo[];\n waiting: readonly File[];\n}) {\n const { t, error: errorText } = useMessages();\n const pages = useMemo(() => group.files.filter((f) => !pageRemoved(f)), [group.files]);\n const total = pages.length + pending.length + queued.length + waiting.length;\n // Local previews bridge an upload until the server's thumbnail arrives.\n const previews = useRef(new Map<string, string>());\n for (const i of queued) if (!previews.current.has(i.path)) previews.current.set(i.path, URL.createObjectURL(i.file));\n useEffect(() => {\n const urls = previews.current;\n return () => urls.forEach((url) => URL.revokeObjectURL(url));\n }, []);\n const locked = disabled || folder.updating;\n const choose = (f: FileInfo) => onSelect(selected === f.path ? null : f);\n return (\n <section className=\"grid gap-1\" data-ckui=\"folder-group\" data-path={group.path}>\n <SortableList\n layout=\"grid\"\n wholeItem\n className=\"grid-cols-[repeat(auto-fill,minmax(8.5rem,1fr))]\"\n items={pages}\n id={(f) => f.path}\n name={(f) => positionalName(pages.indexOf(f) + 1, total, f.path)}\n disabled={locked}\n label={t(`folder.kinds.${ruleKind(group.rule)}`)}\n onMove={(from, to) => void folder.move(pages[from]!.path, group.files.findIndex((f) => f.path === pages[to]!.path)).catch(() => {})}\n row={(f) => ({\n className: cn(TILE, \"cursor-grab active:cursor-grabbing\", selected === f.path ? \"border-primary ring-1 ring-primary/40\" : \"border-border\"),\n \"data-ckui\": \"page-tile\",\n \"data-path\": f.path,\n \"data-selected\": selected === f.path || undefined,\n \"aria-pressed\": selected === f.path,\n onClick: () => choose(f),\n onKeyDown: (e) => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n choose(f);\n },\n })}\n trailing={\n <>\n {pending.map((f, i) => {\n const thumb = thumbnailOf(folder.read.read, f);\n return (\n <li key={f.path} className={cn(TILE, \"border-dashed border-border\")} data-ckui=\"page-tile-pending\">\n <TileImage url={thumb?.url ?? previews.current.get(f.path)} busy={isProcessing(f)} />\n <span className=\"truncate px-0.5 text-xs text-muted-foreground tabular-nums\">\n {positionalName(pages.length + i + 1, total, f.path)} · {f.failed ? errorText(failureError(f.failed)) : auto ? t(\"folder.adding\") : t(\"folder.notAdded\")}\n </span>\n <RemoveTile label={t(\"common.remove\")} disabled={locked} onRemove={() => void folder.remove([f.path]).catch(() => {})} />\n </li>\n );\n })}\n {queued.map((i, n) => {\n const value = i.status === \"uploading\" ? progressValue(i.progress) : null;\n return (\n <li key={i.id} className={cn(TILE, \"border-dashed border-border\")} data-ckui=\"page-tile-upload\" data-status={i.status}>\n <TileImage url={previews.current.get(i.path)} busy />\n {value !== null && <Progress value={value} aria-label={queueLabel(t, errorText, i, auto)} className=\"h-1\" />}\n <span className={cn(\"truncate px-0.5 text-xs tabular-nums\", i.status === \"failed\" ? \"text-destructive\" : \"text-muted-foreground\")} title={i.file.name}>\n {positionalName(pages.length + pending.length + n + 1, total, i.path)} · {queueLabel(t, errorText, i, auto)}\n </span>\n <RemoveTile label={t(\"common.remove\")} onRemove={() => folder.queue.remove(i.id)} />\n </li>\n );\n })}\n {waiting.map((f, n) => (\n <li key={`waiting-${n}`} className={cn(TILE, \"border-dashed border-border\")} data-ckui=\"page-tile-waiting\">\n <TileImage busy />\n <span className=\"truncate px-0.5 text-xs text-muted-foreground\" title={f.name}>\n {t(\"folder.queued\")}\n </span>\n </li>\n ))}\n </>\n }\n >\n {(f, _handle, index) => {\n const busy = isProcessing(f);\n const thumb = thumbnailOf(folder.read.read, f);\n const failure = f.failed ? errorText(failureError(f.failed)) : undefined;\n return (\n <>\n <TileImage url={thumb?.url ?? previews.current.get(f.path)} aspect={thumb?.w && thumb.h ? thumb.w / thumb.h : undefined} busy={busy} />\n <span className=\"flex min-w-0 items-center justify-between gap-1 px-0.5 text-xs text-muted-foreground tabular-nums\">\n <span className=\"truncate\" data-ckui=\"upload-name\" title={f.path}>\n {positionalName(index + 1, total, f.path)}\n </span>\n {failure ? (\n <span className=\"truncate text-destructive\" title={failure} data-ckui=\"failed\">\n {t(\"folder.failed\")}\n </span>\n ) : (\n busy && <span>{t(\"folder.processing\")}</span>\n )}\n </span>\n <RemoveTile label={t(\"common.remove\")} disabled={locked} onRemove={() => void folder.remove([f.path]).catch(() => {})} />\n </>\n );\n }}\n </SortableList>\n </section>\n );\n}\n\nfunction Thumb({ kind, url, busy, grid, aspect }: { kind: Kind; url?: string; busy?: boolean; grid?: boolean; aspect?: number }) {\n return (\n <span className={cn(\"relative flex shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted text-muted-foreground\",grid?\"col-span-2 w-full\":\"size-10\")} style={grid?{aspectRatio:aspect??0.75}:undefined} data-ckui=\"thumb\">\n {url ? <img src={url} alt=\"\" loading=\"lazy\" decoding=\"async\" className=\"size-full object-cover\" /> : <HugeiconsIcon icon={ICONS[kind]} strokeWidth={1.75} className=\"size-4.5\" />}\n {busy && !url && <span aria-hidden className=\"absolute inset-1.5 rounded-full border-2 border-current/25 border-t-current motion-safe:animate-spin\" />}\n </span>\n );\n}\n\nfunction UploadRow({\n file: f,\n grid,\n group,\n handle,\n folder,\n disabled,\n selected,\n onSelect,\n renaming,\n onRename,\n onCrop,\n onReplace,\n actions,\n}: {\n file: FileInfo;\n grid?: boolean;\n group: FolderGroup;\n handle: ReactNode;\n folder: UseMediaFolder;\n disabled: boolean;\n selected: boolean;\n onSelect: (on: boolean) => void;\n renaming: boolean;\n onRename: (path: string | null) => void;\n onCrop: (path: string) => void;\n onReplace: (path: string) => void;\n actions?: ReactNode;\n}) {\n const { t, error: errorText } = useMessages();\n const kind = kindOf(f.type);\n const name = nameIn(group, f.path);\n const busy = isProcessing(f);\n const thumb = useMemo(() => thumbnailOf(folder.read.read, f), [folder.read.read, f]);\n const locked = disabled || folder.updating;\n const failure = f.failed ? errorText(failureError(f.failed)) : undefined;\n return (\n <>\n {handle}\n <input\n type=\"checkbox\"\n className=\"size-4 shrink-0 accent-primary\"\n checked={selected}\n disabled={disabled}\n aria-label={t(\"folder.select\", { name })}\n onChange={(e) => onSelect(e.target.checked)}\n />\n <Thumb kind={kind} url={thumb?.url} busy={busy} grid={grid} aspect={thumb?.w&&thumb.h?thumb.w/thumb.h:undefined} />\n <div className={cn(\"grid min-w-0 flex-1 gap-1\",grid&&\"col-span-2\")}>\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5\">\n {renaming ? (\n <RenameInput name={stem(name)} label={t(\"folder.renameLabel\", { name })} onDone={(to) => (to === null ? onRename(null) : folder.rename(f.path, to).then(() => onRename(null)))} />\n ) : (\n <span className=\"max-w-full truncate text-sm\" title={f.path} data-ckui=\"upload-name\">\n {name}\n </span>\n )}\n {f.edit && (\n <span className=\"shrink-0 rounded-sm border border-border px-1.5 text-[11px] text-muted-foreground\" data-ckui=\"edited\">\n {t(\"folder.edited\")}\n </span>\n )}\n {failure && (\n <span className=\"shrink-0 rounded-sm bg-destructive/10 px-1.5 text-[11px] font-medium text-destructive\" title={failure} data-ckui=\"failed\">\n {kind === \"video\" ? t(\"folder.failedVideo\") : t(\"folder.failed\")}\n </span>\n )}\n </div>\n {failure && <p className=\"text-xs text-destructive\">{failure}</p>}\n {busy && kind === \"video\" && <EncodeProgress progress={f.progress} className=\"max-w-sm text-xs\" />}\n {busy && kind !== \"video\" && <span className=\"text-xs text-muted-foreground\">{t(\"folder.processing\")}</span>}\n </div>\n <span className={cn(\"flex shrink-0 flex-wrap items-center gap-0.5\",grid&&\"col-span-2 justify-end\")} data-ckui=\"upload-actions\">\n {actions}\n {kind === \"image\" && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"folder.crop\")} title={t(\"folder.crop\")} disabled={locked || !!f.staged || !f.size} onClick={() => onCrop(f.path)}>\n <HugeiconsIcon icon={CropIcon} strokeWidth={2} />\n </Button>\n )}\n {!group.rule?.named && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.rename\")} title={t(\"common.rename\")} disabled={locked} onClick={() => onRename(f.path)}>\n <HugeiconsIcon icon={Edit02Icon} strokeWidth={2} />\n </Button>\n )}\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.replace\")} title={t(\"common.replace\")} disabled={locked} onClick={() => onReplace(f.path)}>\n <HugeiconsIcon icon={RepeatIcon} strokeWidth={2} />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} disabled={locked} onClick={() => void folder.remove([f.path]).catch(() => {})}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </span>\n </>\n );\n}\n\nfunction RenameInput({ name, label, onDone }: { name: string; label: string; onDone: (to: string | null) => unknown }) {\n const [value, setValue] = useState(name);\n const done = useRef(false);\n const finish = (to: string | null) => {\n if (done.current) return;\n done.current = true;\n Promise.resolve(onDone(to && to.trim() && to.trim() !== name ? to.trim() : null)).catch(() => (done.current = false));\n };\n return (\n <input\n autoFocus\n aria-label={label}\n value={value}\n className=\"h-7 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-3 focus-visible:ring-ring/50\"\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n finish(value);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n finish(null);\n }\n }}\n onBlur={() => finish(value)}\n data-ckui=\"rename\"\n />\n );\n}\n\n/** An upload on the server not yet added: an earlier visit's, kept across reloads. */\nfunction PendingRow({ file: f, folder, auto, disabled }: { file: FileInfo; folder: UseMediaFolder; auto: boolean; disabled: boolean }) {\n const { t, error: errorText } = useMessages();\n const kind = kindOf(f.type);\n const busy = isProcessing(f);\n const thumb = useMemo(() => thumbnailOf(folder.read.read, f), [folder.read.read, f]);\n const label = f.failed\n ? errorText(failureError(f.failed))\n : busy\n ? f.progress && f.progress.phase !== \"queued\"\n ? t(\"folder.processingPercent\", { percent: Math.round(f.progress.percent) })\n : t(\"folder.processing\")\n : auto\n ? t(\"folder.adding\")\n : t(\"folder.notAdded\");\n return (\n <li className=\"flex min-h-11 items-center gap-2 px-1\" data-ckui=\"pending-row\" data-path={f.path}>\n <Thumb kind={kind} url={thumb?.url} busy={busy} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\" title={f.path}>\n {f.path.slice(f.path.lastIndexOf(\"/\") + 1)}\n </span>\n <span className={cn(\"text-xs\", f.failed ? \"text-destructive\" : \"text-muted-foreground\")} data-ckui=\"queue-status\">\n {label}\n </span>\n </div>\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} disabled={disabled || folder.updating} onClick={() => void folder.remove([f.path]).catch(() => {})}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </li>\n );\n}\n\nfunction queueLabel(t: Translator[\"t\"], errorText: Translator[\"error\"], i: QueueItem, auto: boolean): string {\n if (i.status === \"failed\") return errorText(i.error);\n if (i.status === \"uploading\") return progressLabel(t, i.progress);\n if (i.status === \"uploaded\") {\n const p = i.processing;\n if (p?.failed) return errorText(failureError(p.failed));\n if (i.unattached && !i.processed) return p?.progress && p.progress.phase !== \"queued\" ? t(\"folder.processingPercent\", { percent: Math.round(p.progress.percent) }) : t(\"folder.processing\");\n return auto ? t(\"folder.adding\") : t(\"folder.uploaded\");\n }\n return i.status === \"committed\" ? t(\"folder.adding\") : t(\"folder.queued\");\n}\n\nfunction QueueRow({ item: i, handle, auto, folder }: { item: QueueItem; handle: ReactNode; auto: boolean; folder: UseMediaFolder }) {\n const { t, error: errorText } = useMessages();\n const { queue } = folder;\n const kind = kindOf(i.file.type);\n const label = queueLabel(t, errorText, i, auto);\n const value = i.status === \"uploading\" ? progressValue(i.progress) : i.unattached && !i.processed && i.processing?.progress ? i.processing.progress.percent : null;\n return (\n <>\n {handle}\n <Thumb kind={kind} busy={i.status === \"uploading\" || (!!i.unattached && !i.processed)} />\n <div className=\"grid min-w-0 flex-1 gap-1\">\n <span className=\"truncate text-sm\" title={i.path}>\n {i.file.name}\n </span>\n {value !== null && <Progress value={value} aria-label={label} className=\"max-w-sm\" />}\n <span className={cn(\"text-xs\", i.status === \"failed\" ? \"text-destructive\" : \"text-muted-foreground\")} data-ckui=\"queue-status\">\n {label}\n </span>\n </div>\n <span className=\"flex shrink-0 items-center gap-0.5\">\n {i.status === \"failed\" && (\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.retry\")} title={t(\"common.retry\")} onClick={() => queue.retry(i.id)}>\n <HugeiconsIcon icon={Refresh01Icon} strokeWidth={2} />\n </Button>\n )}\n <Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"common.remove\")} title={t(\"common.remove\")} onClick={() => queue.remove(i.id)}>\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} />\n </Button>\n </span>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA+FA,IAAM,KAAkC;CAAC;CAAI;CAAO;CAAO;AAAM;AAIjE,SAAS,EAAO,GAAgC;CAK9C,OAJI,EAAY,CAAI,IAAU,UAC1B,EAAY,CAAI,IAAU,UAC1B,EAAY,CAAI,IAAU,UAC1B,EAAe,CAAI,IAAU,aAC1B;AACT;AAEA,IAAM,IAAsC;CAAE,OAAO;CAAa,OAAO;CAAa,OAAO;CAAiB,UAAU;CAAY,MAAM;AAAW;AAGrJ,SAAS,EAAS,GAAoC;CACpD,IAAM,IAAQ,IAAI,KAAK,GAAM,SAAS,CAAC,EAAA,CAAG,IAAI,CAAM,CAAC;CACrD,OAAO,EAAM,SAAS,IAAI,CAAC,GAAG,CAAK,CAAC,CAAC,KAAM;AAC7C;AAGA,SAAgB,GAAc,GAAoB,GAAsC;CACtF,IAAM,IAAkB,CAAC;CACzB,KAAK,IAAM,KAAK,GAAO;EACrB,IAAI,CAAC,EAAE,MAAM,QAAQ;EACrB,IAAM,IAAO,EAAE,gBAAgB,EAAS,CAAC,GAAG,GACtC,IAAO,EAAE,YAAY,IAAI,EAAE,oBAAoB;GAAE;GAAM,MAAM,EAAU,EAAE,SAAS;EAAE,CAAC,IAAI;EAE/F,AADA,EAAM,KAAK,EAAE,MAAM,GAAG,EAAK,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAI,GACxE,EAAE,cAAc,EAAE,cAAY,EAAM,KAAK,EAAE,sBAAsB;GAAE,KAAK,EAAW,EAAE,UAAU;GAAG,KAAK,EAAW,EAAE,UAAU;EAAE,CAAC,CAAC;CACxI;CACA,OAAO,EAAM,KAAK,KAAK;AACzB;AAUA,SAAgB,GAAkB,GAA2B;CAE3D,IAAI,EAAE,QAAQ;EACZ,IAAM,EAAE,WAAQ,GAAG,MAAS;EAC5B,OAAO,kBAAC,GAAD;GAAgE;GAAQ,GAAI;EAAO,GAAlE,EAAO,MAAM,EAAQ,EAAO,GAAG,IAAI,EAA+B;CAC5F;CAEA,OAAO,kBAAC,GAAD,EAAiC,GAAI,EAAI,GAAzB,EAAQ,EAAE,IAAI,CAAW;AAClD;AAEA,SAAS,EAAU,GAAwE;CACzF,IAAM,EAAE,SAAM,QAAK,UAAO,WAAQ,eAAY,YAAS,eAAY,WAAQ,YAAS,kBAAe,aAAU,cAAW,eAAY,iBAAc,iBAAc,GAAG,MAAY,GACzK,IAAS,EAAe,GAAM,CAAO;CAC3C,OAAO,kBAAC,GAAD;EAAkB;EAAQ;EAAK;EAAO;EAAQ;EAAY;EAAS;EAAY;EAAQ;EAAS;EAAe;EAAU;EAAW;EAAY;EAAc;CAAiB,CAAA;AACxL;AAEA,IAAM,KAAmB;CAAE,MAAM;CAAI,IAAI;AAAG;AAE5C,SAAS,EAAW,GAA4D;CAC9E,IAAM,EAAE,WAAQ,QAAK,UAAO,WAAQ,eAAY,YAAS,eAAY,WAAQ,aAAU,IAAS,kBAAe,aAAU,cAAW,eAAY,kBAAc,oBAAiB,GACzK,EAAE,MAAG,OAAO,MAAc,EAAY,GACtC,EAAE,WAAQ,UAAO,SAAM,eAAY;CACzC,GAAoB,UAAY;EAAE,SAAS,EAAO;EAAS,QAAQ,EAAO;EAAQ;CAAO,IAAI,CAAC,CAAM,CAAC;CACrG,IAAM,IAAO,EAAQ,WAAW,QAC1B,IAAQ,EAAO,SAAS,MAAO,EAAE,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC,CAAE,GACtD,KAAS,EAAS,CAAK,GAEvB,KADQ,EAAO,QAAQ,SAAS,EAAM,MAAM,SAAS,EAAO,QAAQ,SAAS,EAAO,QAAQ,WAC1E,GAClB,IAAM,CAAC,CAAC,GAER,CAAC,GAAU,KAAe,kBAA8B,IAAI,IAAI,CAAC;CACvE,SAAgB;EACd,IAAM,IAAQ,IAAI,IAAI,EAAO,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC;EACvD,GAAa,MAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,MAAM,EAAM,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAM,IAAI,CAAC,CAAC,CAAC,CAAE;CAC1G,GAAG,CAAC,EAAO,OAAO,CAAC;CACnB,IAAM,CAAC,GAAU,MAAe,EAAwB,IAAI,GACtD,IAAO,EAAc,EAAO,OAAO,IAAS,GAAU;EAAE,QAAQ,EAAQ;EAAQ,SAAS,EAAQ;EAAS,eAAe,GAAY,IAAI;CAAE,CAAC,GAC5I,IAAW,IAAW,EAAO,MAAM,MAAM,EAAE,MAAM,MAAM,MAAM,EAAE,SAAS,CAAQ,CAAC,CAAC,EAAE,OAAO,KAAA,GAC3F,CAAC,GAAU,KAAe,EAAwB,IAAI,GACtD,IAAe,GAAyB,IAAI,GAC5C,CAAC,GAAW,MAAgB,EAAwB,IAAI,GACxD,CAAC,IAAM,KAAW,EAAS,EAAK,GAEhC,KAAO;EACX,aAAa,MAAiB;GACxB,MAAQ,EAAE,aAAa,MAAM,SAAS,OAAO,MACjD,EAAE,eAAe,GACjB,EAAQ,EAAI;EACd;EACA,cAAc,MAAiB;GAC7B,AAAK,EAAE,cAAc,SAAS,EAAE,aAA4B,KAAG,EAAQ,EAAK;EAC9E;EACA,SAAS,MAAiB;GACpB,MAAQ,EAAE,aAAa,MAAM,WACjC,EAAE,eAAe,GACjB,EAAQ,EAAK,GACb,EAAO,IAAI,EAAE,aAAa,KAAK;EACjC;CACF,GAEM,KAAiB,YAAY;EACjC,IAAM,IAAQ,CAAC,GAAG,CAAQ;EACf,OAAkB,OAAe,IAAgB,MAAM,EAAc,EAAM,MAAM,IAAI,WAAW,UAAU,EAAE,wBAAwB,EAAE,OAAO,EAAM,OAAO,CAAC,CAAC,KAAK,QAE5K,MAAM,EAAO,OAAO,CAAK,CAAC,CAAC,WAAW,kBAAY,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;CACxE,GAEM,KAAW,EAAM,MAAM,QAAQ,MAAM,EAAE,WAAW,UAAU,CAAC,CAAC,SAAS,EAAO,QAAQ,QAEtF,IAAY,MAAW,SAAS,EAAO,MAAM,MAAM,EAAE,MAAM,IAAI,IAAI,KAAA,GACnE,MAAW,MAAiB,CAAC,CAAC,KAAa,EAAQ,GAAO,CAAI,CAAC,EAAE,SAAS,EAAU,KAAM,MAC1F,KAAY,EAAM,MAAM,QAAQ,MAAM,GAAQ,EAAE,IAAI,CAAC,GACrD,KAAa,EAAM,MAAM,QAAQ,MAAM,CAAC,GAAQ,EAAE,IAAI,CAAC,GACvD,KAAc,EAAO,QAAQ,QAAQ,MAAM,GAAQ,EAAE,IAAI,CAAC,GAC1D,KAAe,EAAO,QAAQ,QAAQ,MAAM,CAAC,GAAQ,EAAE,IAAI,CAAC,GAC5D,KAAc,IAAY,EAAO,QAAQ,QAAQ,MAAM,EAAY,EAAE,IAAI,CAAC,IAAI,CAAC,GAC/E,KAAe,IAAY,EAAO,QAAQ,QAAQ,MAAM,CAAC,EAAY,EAAE,IAAI,CAAC,IAAI,EAAO,SACvF,MAAU,MACd,kBAAC,SAAD;EACE,WAAW,EACT,IACI,+NACA,+MACJ,KAAO,MAAQ,+BACf,KAAO,gCACT;EACA,aAAW,IAAM,gBAAgB;EARnC,UAAA;GAUE,kBAAC,GAAD;IAAe,MAAM;IAAgB,aAAa;IAAM,WAAW,IAAM,WAAW;GAAW,CAAA;GAC9F,IAAM,kBAAC,UAAD;IAAQ,WAAU;IAA+B,UAAA,EAAE,aAAa;GAAU,CAAA,IAAI,EAAE,YAAY;GAClG,KAAO,EAAM,SAAS,KAAK,kBAAC,QAAD;IAAM,WAAU;IAAW,UAAA,GAAc,GAAG,CAAK;GAAQ,CAAA;GACrF,kBAAC,SAAD;IACE,MAAK;IACL,UAAA;IACQ;IACR,WAAU;IACV,UAAU;IACV,aAAU;IACV,cAAY;IACZ,WAAW,MAAM;KAEf,AADA,EAAO,IAAI,CAAC,GAAI,EAAE,OAAO,SAAS,CAAC,CAAE,CAAC,GACtC,EAAE,OAAO,QAAQ;IACnB;GACD,CAAA;EACI;;CAGT,OACE,kBAAC,GAAD;EAA8B;EAAY,WAAW,EAAG,cAAc,CAAS;EAAG,aAAU;EAAe,aAAW,KAAO,KAAK,KAAA;EAAW,GAAI;EAAjJ,UAAA;GACE,kBAAC,OAAD;IAAK,WAAU;IAAoD,aAAU;IAA7E,UAAA,CACG,MAAU,MAAS,kBAAC,MAAD;KAAI,WAAU;KAAyB,UAAA,KAAS,EAAE,cAAc;IAAM,CAAA,GAC1F,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACG,GACA,CAAC,MAAS,GAAO,EAAK,CACpB;IACF,CAAA,CAAA;;GACJ,OAAU,EAAK,QAAQ,CAAC,EAAO,QAAQ,GAAO,EAAI;GAClD,MAAS,CAAC,EAAK,QAAQ,EAAK,WAC3B,kBAAC,OAAD;IAAK,WAAU;IAAiD,aAAU;IACxE,UAAA,kBAAC,GAAD;KAAe,MAAM;KAAe,aAAa;KAAG,WAAU;IAAmC,CAAA;GAC9F,CAAA;GAGN,EAAO,QAAQ,SAAS,KACvB,kBAAC,GAAD;IAAO,SAAQ;IAAc,MAAK;IAAQ,aAAU;IAApD,UAAA,CACE,kBAAC,GAAD;KAAe,MAAM;KAAa,aAAa;IAAI,CAAA,GACnD,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;KACX,UAAA,EAAO,QAAQ,KAAK,GAAG,MACtB,kBAAC,MAAD,EAAA,UAAA;MACE,kBAAC,QAAD;OAAM,WAAU;OAAe,UAAA,EAAE,KAAK;MAAW,CAAA;MAAC;MAAG,EAAU,EAAE,KAAK;KACpE,EAAA,GAFK,CAEL,CACL;IACC,CAAA,GACJ,kBAAC,GAAD;KAAQ,SAAQ;KAAU,MAAK;KAAK,WAAU;KAAa,SAAS,EAAO;KACxE,UAAA,EAAE,gBAAgB;IACb,CAAA,CACQ,EAAA,CAAA,CACb;;GAER,EAAM,WACL,kBAAC,GAAD;IAAO,SAAQ;IAAc,MAAK;IAAQ,aAAU;IAApD,UAAA;KACE,kBAAC,GAAD;MAAe,MAAM;MAAa,aAAa;KAAI,CAAA;KACnD,kBAAC,GAAD,EAAA,UAAa,EAAE,eAAe,EAAc,CAAA;KAC5C,kBAAC,GAAD,EAAA,UAAA,CACG,EAAU,EAAM,OAAO,GACxB,kBAAC,GAAD;MAAQ,SAAQ;MAAU,MAAK;MAAK,WAAU;MAAa,eAAe,EAAM,MAAM;MACnF,UAAA,EAAE,eAAe;KACZ,CAAA,CACQ,EAAA,CAAA;IACb;;GAER,EAAO,SACN,kBAAC,GAAD;IAAO,SAAQ;IAAc,MAAK;IAAQ,aAAU;IAApD,UAAA,CACE,kBAAC,GAAD;KAAe,MAAM;KAAa,aAAa;IAAI,CAAA,GACnD,kBAAC,GAAD,EAAA,UAAmB,EAAU,EAAO,KAAK,EAAoB,CAAA,CACxD;;GAGR,EAAS,OAAO,KACf,kBAAC,OAAD;IAAK,WAAU;IAA4E,aAAU;IAArG,UAAA;KACE,kBAAC,QAAD;MAAM,WAAU;MAAgB,UAAA,EAAE,mBAAmB,EAAE,OAAO,EAAS,KAAK,CAAC;KAAQ,CAAA;KACrF,kBAAC,GAAD;MAAQ,SAAQ;MAAc,MAAK;MAAK,UAAU,KAAO,EAAO;MAAU,eAAe,KAAK,GAAe;MAA7G,UAAA,CACE,kBAAC,GAAD;OAAe,MAAM;OAAc,aAAa;MAAI,CAAA,GACnD,EAAE,uBAAuB,CACpB;;KACR,kBAAC,GAAD;MAAQ,SAAQ;MAAQ,MAAK;MAAK,eAAe,kBAAY,IAAI,IAAI,CAAC;MACnE,UAAA,EAAE,uBAAuB;KACpB,CAAA;IACL;;GAGN,EAAO,KAAK,MACX,MAAM,IACJ,EAAE,MAAM,SAAS,GAAU,SAAS,GAAY,SAAS,GAAY,SAAS,KAC5E,kBAAC,IAAD;IAEE,OAAO;IACC;IACR,UAAU;IACJ;IACN,UAAU,MAAgB;IAC1B,WAAW,MAAM,IAAe,CAAC;IACjC,QAAQ;IACR,SAAS;IACT,SAAS;GACV,GAVM,EAAE,IAUR,IAED,EAAE,MAAM,SACV,kBAAC,IAAD;IAEE,OAAO;IACP,QAAQ,MAAW,UAAU,EAAE,MAAM,OAAO,SAAS;IACrD,QAAQ,EAAO,SAAS;IAChB;IACR,UAAU;IACA;IACV,WAAW,GAAM,MAAO,GAAa,MAAO,oBAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAI,CAAC,CAAE;IACzG;IACV,UAAU;IACV,QAAQ;IACR,YAAY,MAAS;KAEnB,AADA,GAAa,CAAI,GACjB,EAAa,SAAS,MAAM;IAC9B;IACY;GACb,GAhBM,EAAE,IAgBR,IACC,IACN;GAEC,GAAa,SAAS,KACrB,kBAAC,MAAD;IAAI,WAAU;IAAO,cAAY,EAAE,cAAc;IAC9C,UAAA,GAAa,KAAK,GAAG,MACpB,kBAAC,MAAD;KAAY,WAAU;KAAwC,aAAU;KAAY,eAAY;KAAhG,UAAA,CACE,kBAAC,IAAD,EAAO,MAAM,EAAO,EAAE,IAAI,EAAI,CAAA,GAC9B,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,QAAD;OAAM,WAAU;OAAoB,UAAA,EAAE;MAAW,CAAA,GACjD,kBAAC,QAAD;OAAM,WAAU;OAAgC,aAAU;OACvD,UAAA,EAAE,eAAe;MACd,CAAA,CACH;KACH,CAAA,CAAA;IARK,GAAA,CAQL,CACL;GACC,CAAA;GAGL,GAAa,SAAS,KACrB,kBAAC,MAAD;IAAI,WAAU;IAAO,cAAY,EAAE,cAAc;IAAG,aAAU;IAC3D,UAAA,GAAa,KAAK,MACjB,kBAAC,IAAD;KAAyB,MAAM;KAAW;KAAc;KAAM,UAAU;IAAM,GAA7D,EAAE,IAA2D,CAC/E;GACC,CAAA;GAGL,GAAW,SAAS,KACnB,kBAAC,GAAD;IACE,OAAO;IACP,KAAK,MAAM,EAAE;IACb,OAAO,MAAM,EAAE,KAAK;IACpB,UAAU,KAAQ;IAClB,OAAO,EAAE,cAAc;IACvB,SAAS,GAAM,MAAO,EAAM,KAAK,GAAW,EAAK,CAAE,IAAI,EAAM,MAAM,QAAQ,GAAW,EAAI,CAAC;IAC3F,MAAM,OAAO;KAAE,WAAW;KAAyC,aAAa;KAAa,eAAe,EAAE;IAAO;IAEnH,WAAA,GAAG,MAAW,kBAAC,IAAD;KAAU,MAAM;KAAG,QAAQ,IAAO,OAAO;KAAc;KAAc;IAAS,CAAA;GAClF,CAAA;IAGb,CAAC,KAAQ,KAAW,KAAO,KAAQ,EAAO,SAAS,KAAW,MAC/D,kBAAC,GAAD;IAAQ,WAAU;IAAQ,UAAU,KAAQ,EAAM,MAAM,SAAS,KAAK,CAAC,EAAM,SAAU,EAAO;IAAY,eAAe,KAAK,EAAO,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;IAAG,aAAU;IAAzK,UAAA,CACG,EAAO,cAAc,kBAAC,GAAD;KAAe,MAAM;KAAe,aAAa;KAAG,WAAU;IAA4B,CAAA,GAC/G,IAAO,EAAE,oBAAoB,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAM,MAAM,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC,CAAC,SAAS,EAAO,QAAQ,OAAO,CAAC,CAC5I;;GAET;GAED,kBAAC,SAAD;IACE,KAAK;IACL,MAAK;IACG;IACR,WAAU;IACV,UAAU;IACV,eAAA;IACA,WAAW,MAAM;KACf,IAAM,IAAI,EAAE,OAAO,QAAQ;KAG3B,AAFA,EAAE,OAAO,QAAQ,IACb,KAAK,KAAW,EAAY,QAAQ,GAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GACpE,GAAa,IAAI;IACnB;GACD,CAAA;GACD,kBAAC,GAAD;IACE,MAAM,CAAC,CAAC;IACR,eAAe,MAAM,CAAC,KAAK,EAAK,WAAW,YAAY,GAAY,IAAI;IACvE,QAAQ,YAAY,IAAQ,EAAK,UAAU,OAAQ;IACnD,QAAQ,GAAU,UAAU;IAC5B,SAAS,GAAU,SAAS,KAAA,IAAY;IACxC,aAAa,UAAU,IAAO,EAAK,OAAO;IAC1C,UAAU,GAAU;IACpB,OAAO,EAAE,aAAa;IACtB,MAAM,EAAK,WAAW;IACtB,OAAO,EAAK,WAAW,UAAU,EAAU,EAAK,KAAK,IAAI,KAAA;IACzD,YAAY,MAAS,KAAK,EAAK,KAAK,CAAI;GACzC,CAAA;EACe;;AAEtB;AAEA,SAAS,GAAM,EACb,UACA,WACA,WACA,WACA,aACA,aACA,aACA,aACA,aACA,WACA,cACA,iBAcC;CACD,IAAM,EAAE,SAAM,EAAY,GAEpB,IAAQ,EAAE,gBADH,EAAS,EAAM,IACI,GAAM,GAChC,IAAM,EAAM,MAAM;CACxB,OACE,kBAAC,WAAD;EAAS,WAAU;EAAa,aAAU;EAAe,aAAW,EAAM;EAA1E,UAAA,CACG,KACC,kBAAC,MAAD;GAAI,WAAU;GAAd,UAAA;IACG;IAAM;IAAI,IAAM,GAAG,EAAM,MAAM,OAAO,KAAK,MAAQ,EAAM,MAAM;GAC9D;EAEN,CAAA,GAAA,kBAAC,GAAD;GACU;GACR,WAAW,MAAW,SAAS,oDAAoD,KAAA;GACnF,OAAO,EAAM;GACb,KAAK,MAAM,EAAE;GACb,OAAO,MAAM,GAAO,GAAO,EAAE,IAAI;GACjC,UAAU,KAAY,EAAO;GAC7B,OAAO;GACP,SAAS,GAAM,MAAO,KAAK,EAAO,KAAK,EAAM,MAAM,EAAK,CAAE,MAAM,CAAE,CAAC,CAAC,YAAY,CAAC,CAAC;GAClF,MAAM,OAAO;IAAE,WAAW,MAAW,SAAS,oHAAoH;IAAyC,aAAa;IAAc,aAAa,EAAE;GAAK;GAExP,WAAA,GAAG,MACH,kBAAC,IAAD;IACE,MAAM;IACN,MAAM,MAAW;IACV;IACC;IACA;IACE;IACV,UAAU,EAAS,IAAI,EAAE,IAAI;IAC7B,WAAW,MAAO,EAAS,EAAE,MAAM,CAAE;IACrC,UAAU,MAAa,EAAE;IACf;IACF;IACG;IACX,SAAS,IAAa,CAAC;GACxB,CAAA;EAES,CAAA,CACP;;AAEb;AAGA,SAAgB,EAAe,GAAkB,GAAe,GAAsB;CACpF,IAAM,IAAM,EAAK,YAAY,GAAG,GAC1B,IAAM,IAAM,EAAK,YAAY,GAAG,IAAI,EAAK,MAAM,CAAG,CAAC,CAAC,YAAY,IAAI;CAC1E,OAAO,OAAO,CAAQ,CAAC,CAAC,SAAS,KAAK,IAAI,GAAG,OAAO,CAAK,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI;AAC7E;AAEA,IAAM,IAAO;AAEb,SAAS,EAAW,EAAE,UAAO,aAAU,eAAyE;CAC9G,OACE,kBAAC,UAAD;EACE,MAAK;EACL,cAAY;EACZ,OAAO;EACG;EACV,WAAU;EACV,gBAAgB,MAAM,EAAE,gBAAgB;EACxC,YAAY,MAAM,EAAE,gBAAgB;EACpC,UAAU,MAAM;GAEd,AADA,EAAE,gBAAgB,GAClB,EAAS;EACX;EACA,aAAU;EAEV,UAAA,kBAAC,GAAD;GAAe,MAAM;GAAc,aAAa;GAAG,WAAU;EAAY,CAAA;CACnE,CAAA;AAEZ;AAEA,SAAS,EAAU,EAAE,QAAK,WAAQ,WAA2D;CAC3F,OACE,kBAAC,QAAD;EAAM,WAAU;EAA4D,OAAO,EAAE,aAAa,KAAU,IAAK;EAAjH,UAAA,CACG,KAAO,kBAAC,OAAD;GAAK,KAAK;GAAK,KAAI;GAAG,SAAQ;GAAO,UAAS;GAAQ,WAAW;GAAO,WAAW,EAAG,0BAA0B,KAAQ,YAAY;EAAI,CAAA,GAC/I,KAAQ,CAAC,KAAO,kBAAC,QAAD;GAAM,eAAA;GAAY,WAAU;EAAgI,CAAA,CACzK;;AAEV;AAOA,SAAS,GAAS,EAChB,UACA,WACA,aACA,SACA,aACA,aACA,WACA,YACA,cAWC;CACD,IAAM,EAAE,MAAG,OAAO,MAAc,EAAY,GACtC,IAAQ,QAAc,EAAM,MAAM,QAAQ,MAAM,CAAC,EAAY,CAAC,CAAC,GAAG,CAAC,EAAM,KAAK,CAAC,GAC/E,IAAQ,EAAM,SAAS,EAAQ,SAAS,EAAO,SAAS,EAAQ,QAEhE,IAAW,mBAAO,IAAI,IAAoB,CAAC;CACjD,KAAK,IAAM,KAAK,GAAQ,AAAK,EAAS,QAAQ,IAAI,EAAE,IAAI,KAAG,EAAS,QAAQ,IAAI,EAAE,MAAM,IAAI,gBAAgB,EAAE,IAAI,CAAC;CACnH,SAAgB;EACd,IAAM,IAAO,EAAS;EACtB,aAAa,EAAK,SAAS,MAAQ,IAAI,gBAAgB,CAAG,CAAC;CAC7D,GAAG,CAAC,CAAC;CACL,IAAM,IAAS,KAAY,EAAO,UAC5B,KAAU,MAAgB,EAAS,MAAa,EAAE,OAAO,OAAO,CAAC;CACvE,OACE,kBAAC,WAAD;EAAS,WAAU;EAAa,aAAU;EAAe,aAAW,EAAM;EACxE,UAAA,kBAAC,GAAD;GACE,QAAO;GACP,WAAA;GACA,WAAU;GACV,OAAO;GACP,KAAK,MAAM,EAAE;GACb,OAAO,MAAM,EAAe,EAAM,QAAQ,CAAC,IAAI,GAAG,GAAO,EAAE,IAAI;GAC/D,UAAU;GACV,OAAO,EAAE,gBAAgB,EAAS,EAAM,IAAI,GAAG;GAC/C,SAAS,GAAM,MAAO,KAAK,EAAO,KAAK,EAAM,EAAK,CAAE,MAAM,EAAM,MAAM,WAAW,MAAM,EAAE,SAAS,EAAM,EAAG,CAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;GAClI,MAAM,OAAO;IACX,WAAW,EAAG,GAAM,sCAAsC,MAAa,EAAE,OAAO,0CAA0C,eAAe;IACzI,aAAa;IACb,aAAa,EAAE;IACf,iBAAiB,MAAa,EAAE,QAAQ,KAAA;IACxC,gBAAgB,MAAa,EAAE;IAC/B,eAAe,EAAO,CAAC;IACvB,YAAY,MAAM;KACZ,EAAE,QAAQ,YACd,EAAE,eAAe,GACjB,EAAO,CAAC;IACV;GACF;GACA,UACE,kBAAA,GAAA,EAAA,UAAA;IACG,EAAQ,KAAK,GAAG,MAAM;KACrB,IAAM,IAAQ,EAAY,EAAO,KAAK,MAAM,CAAC;KAC7C,OACE,kBAAC,MAAD;MAAiB,WAAW,EAAG,GAAM,6BAA6B;MAAG,aAAU;MAA/E,UAAA;OACE,kBAAC,GAAD;QAAW,KAAK,GAAO,OAAO,EAAS,QAAQ,IAAI,EAAE,IAAI;QAAG,MAAM,EAAa,CAAC;OAAI,CAAA;OACpF,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SACG,EAAe,EAAM,SAAS,IAAI,GAAG,GAAO,EAAE,IAAI;SAAE;SAAI,EAAE,SAAS,EAAU,EAAa,EAAE,MAAM,CAAC,IAAW,EAAP,IAAS,kBAAqB,iBAAiB;QACnJ;;OACN,kBAAC,GAAD;QAAY,OAAO,EAAE,eAAe;QAAG,UAAU;QAAQ,gBAAgB,KAAK,EAAO,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;OAAI,CAAA;MACtH;KANK,GAAA,EAAE,IAMP;IAER,CAAC;IACA,EAAO,KAAK,GAAG,MAAM;KACpB,IAAM,IAAQ,EAAE,WAAW,cAAc,EAAc,EAAE,QAAQ,IAAI;KACrE,OACE,kBAAC,MAAD;MAAe,WAAW,EAAG,GAAM,6BAA6B;MAAG,aAAU;MAAmB,eAAa,EAAE;MAA/G,UAAA;OACE,kBAAC,GAAD;QAAW,KAAK,EAAS,QAAQ,IAAI,EAAE,IAAI;QAAG,MAAA;OAAM,CAAA;OACnD,MAAU,QAAQ,kBAAC,GAAD;QAAiB;QAAO,cAAY,EAAW,GAAG,GAAW,GAAG,CAAI;QAAG,WAAU;OAAO,CAAA;OAC3G,kBAAC,QAAD;QAAM,WAAW,EAAG,wCAAwC,EAAE,WAAW,WAAW,qBAAqB,uBAAuB;QAAG,OAAO,EAAE,KAAK;QAAjJ,UAAA;SACG,EAAe,EAAM,SAAS,EAAQ,SAAS,IAAI,GAAG,GAAO,EAAE,IAAI;SAAE;SAAI,EAAW,GAAG,GAAW,GAAG,CAAI;QACtG;;OACN,kBAAC,GAAD;QAAY,OAAO,EAAE,eAAe;QAAG,gBAAgB,EAAO,MAAM,OAAO,EAAE,EAAE;OAAI,CAAA;MACjF;KAPK,GAAA,EAAE,EAOP;IAER,CAAC;IACA,EAAQ,KAAK,GAAG,MACf,kBAAC,MAAD;KAAyB,WAAW,EAAG,GAAM,6BAA6B;KAAG,aAAU;KAAvF,UAAA,CACE,kBAAC,GAAD,EAAW,MAAA,GAAM,CAAA,GACjB,kBAAC,QAAD;MAAM,WAAU;MAAgD,OAAO,EAAE;MACtE,UAAA,EAAE,eAAe;KACd,CAAA,CACJ;IALK,GAAA,WAAW,GAKhB,CACL;GACD,EAAA,CAAA;GAGF,WAAA,GAAG,GAAS,MAAU;IACtB,IAAM,IAAO,EAAa,CAAC,GACrB,IAAQ,EAAY,EAAO,KAAK,MAAM,CAAC,GACvC,IAAU,EAAE,SAAS,EAAU,EAAa,EAAE,MAAM,CAAC,IAAI,KAAA;IAC/D,OACE,kBAAA,GAAA,EAAA,UAAA;KACE,kBAAC,GAAD;MAAW,KAAK,GAAO,OAAO,EAAS,QAAQ,IAAI,EAAE,IAAI;MAAG,QAAQ,GAAO,KAAK,EAAM,IAAI,EAAM,IAAI,EAAM,IAAI,KAAA;MAAiB;KAAO,CAAA;KACtI,kBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACE,kBAAC,QAAD;OAAM,WAAU;OAAW,aAAU;OAAc,OAAO,EAAE;OACzD,UAAA,EAAe,IAAQ,GAAG,GAAO,EAAE,IAAI;MACpC,CAAA,GACL,IACC,kBAAC,QAAD;OAAM,WAAU;OAA4B,OAAO;OAAS,aAAU;OACnE,UAAA,EAAE,eAAe;MACd,CAAA,IAEN,KAAQ,kBAAC,QAAD,EAAA,UAAO,EAAE,mBAAmB,EAAQ,CAAA,CAE1C;;KACN,kBAAC,GAAD;MAAY,OAAO,EAAE,eAAe;MAAG,UAAU;MAAQ,gBAAgB,KAAK,EAAO,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;KAAI,CAAA;IACxH,EAAA,CAAA;GAEN;EACY,CAAA;CACP,CAAA;AAEb;AAEA,SAAS,GAAM,EAAE,SAAM,QAAK,SAAM,SAAM,aAAyF;CAC/H,OACE,kBAAC,QAAD;EAAM,WAAW,EAAG,gHAA+G,IAAK,sBAAoB,SAAS;EAAG,OAAO,IAAK,EAAC,aAAY,KAAQ,IAAI,IAAE,KAAA;EAAW,aAAU;EAApO,UAAA,CACG,IAAM,kBAAC,OAAD;GAAK,KAAK;GAAK,KAAI;GAAG,SAAQ;GAAO,UAAS;GAAQ,WAAU;EAA0B,CAAA,IAAI,kBAAC,GAAD;GAAe,MAAM,EAAM;GAAO,aAAa;GAAM,WAAU;EAAY,CAAA,GAC/K,KAAQ,CAAC,KAAO,kBAAC,QAAD;GAAM,eAAA;GAAY,WAAU;EAAwG,CAAA,CACjJ;;AAEV;AAEA,SAAS,GAAU,EACjB,MAAM,GACN,SACA,UACA,WACA,WACA,aACA,aACA,aACA,aACA,aACA,WACA,cACA,cAeC;CACD,IAAM,EAAE,MAAG,OAAO,MAAc,EAAY,GACtC,IAAO,EAAO,EAAE,IAAI,GACpB,IAAO,GAAO,GAAO,EAAE,IAAI,GAC3B,IAAO,EAAa,CAAC,GACrB,IAAQ,QAAc,EAAY,EAAO,KAAK,MAAM,CAAC,GAAG,CAAC,EAAO,KAAK,MAAM,CAAC,CAAC,GAC7E,IAAS,KAAY,EAAO,UAC5B,IAAU,EAAE,SAAS,EAAU,EAAa,EAAE,MAAM,CAAC,IAAI,KAAA;CAC/D,OACE,kBAAA,GAAA,EAAA,UAAA;EACG;EACD,kBAAC,SAAD;GACE,MAAK;GACL,WAAU;GACV,SAAS;GACC;GACV,cAAY,EAAE,iBAAiB,EAAE,QAAK,CAAC;GACvC,WAAW,MAAM,EAAS,EAAE,OAAO,OAAO;EAC3C,CAAA;EACD,kBAAC,IAAD;GAAa;GAAM,KAAK,GAAO;GAAW;GAAY;GAAM,QAAQ,GAAO,KAAG,EAAM,IAAE,EAAM,IAAE,EAAM,IAAE,KAAA;EAAY,CAAA;EAClH,kBAAC,OAAD;GAAK,WAAW,EAAG,6BAA4B,KAAM,YAAY;GAAjE,UAAA;IACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACG,IACC,kBAAC,IAAD;OAAa,MAAM,EAAK,CAAI;OAAG,OAAO,EAAE,sBAAsB,EAAE,QAAK,CAAC;OAAG,SAAS,MAAQ,MAAO,OAAO,EAAS,IAAI,IAAI,EAAO,OAAO,EAAE,MAAM,CAAE,CAAC,CAAC,WAAW,EAAS,IAAI,CAAC;MAAK,CAAA,IAEjL,kBAAC,QAAD;OAAM,WAAU;OAA8B,OAAO,EAAE;OAAM,aAAU;OACpE,UAAA;MACG,CAAA;MAEP,EAAE,QACD,kBAAC,QAAD;OAAM,WAAU;OAAoF,aAAU;OAC3G,UAAA,EAAE,eAAe;MACd,CAAA;MAEP,KACC,kBAAC,QAAD;OAAM,WAAU;OAAwF,OAAO;OAAS,aAAU;OAC/H,UAAmB,EAAnB,MAAS,UAAY,uBAA0B,eAAe;MAC3D,CAAA;KAEL;;IACJ,KAAW,kBAAC,KAAD;KAAG,WAAU;KAA4B,UAAA;IAAW,CAAA;IAC/D,KAAQ,MAAS,WAAW,kBAAC,GAAD;KAAgB,UAAU,EAAE;KAAU,WAAU;IAAoB,CAAA;IAChG,KAAQ,MAAS,WAAW,kBAAC,QAAD;KAAM,WAAU;KAAiC,UAAA,EAAE,mBAAmB;IAAQ,CAAA;GACxG;;EACL,kBAAC,QAAD;GAAM,WAAW,EAAG,gDAA+C,KAAM,wBAAwB;GAAG,aAAU;GAA9G,UAAA;IACG;IACA,MAAS,WACR,kBAAC,GAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAU,cAAY,EAAE,aAAa;KAAG,OAAO,EAAE,aAAa;KAAG,UAAU,KAAU,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE;KAAM,eAAe,EAAO,EAAE,IAAI;KACnK,UAAA,kBAAC,GAAD;MAAe,MAAM;MAAU,aAAa;KAAI,CAAA;IAC1C,CAAA;IAET,CAAC,EAAM,MAAM,SACZ,kBAAC,GAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAU,cAAY,EAAE,eAAe;KAAG,OAAO,EAAE,eAAe;KAAG,UAAU;KAAQ,eAAe,EAAS,EAAE,IAAI;KAChJ,UAAA,kBAAC,GAAD;MAAe,MAAM;MAAY,aAAa;KAAI,CAAA;IAC5C,CAAA;IAEV,kBAAC,GAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAU,cAAY,EAAE,gBAAgB;KAAG,OAAO,EAAE,gBAAgB;KAAG,UAAU;KAAQ,eAAe,EAAU,EAAE,IAAI;KACnJ,UAAA,kBAAC,GAAD;MAAe,MAAM;MAAY,aAAa;KAAI,CAAA;IAC5C,CAAA;IACR,kBAAC,GAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAU,cAAY,EAAE,eAAe;KAAG,OAAO,EAAE,eAAe;KAAG,UAAU;KAAQ,eAAe,KAAK,EAAO,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;KAC5K,UAAA,kBAAC,GAAD;MAAe,MAAM;MAAc,aAAa;KAAI,CAAA;IAC9C,CAAA;GACJ;;CACN,EAAA,CAAA;AAEN;AAEA,SAAS,GAAY,EAAE,SAAM,UAAO,aAAmF;CACrH,IAAM,CAAC,GAAO,KAAY,EAAS,CAAI,GACjC,IAAO,GAAO,EAAK,GACnB,KAAU,MAAsB;EAChC,EAAK,YACT,EAAK,UAAU,IACf,QAAQ,QAAQ,EAAO,KAAM,EAAG,KAAK,KAAK,EAAG,KAAK,MAAM,IAAO,EAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,YAAa,EAAK,UAAU,EAAM;CACtH;CACA,OACE,kBAAC,SAAD;EACE,WAAA;EACA,cAAY;EACL;EACP,WAAU;EACV,WAAW,MAAM,EAAS,EAAE,OAAO,KAAK;EACxC,YAAY,MAAM;GAChB,AAAI,EAAE,QAAQ,WACZ,EAAE,eAAe,GACjB,EAAO,CAAK,KACH,EAAE,QAAQ,aACnB,EAAE,eAAe,GACjB,EAAO,IAAI;EAEf;EACA,cAAc,EAAO,CAAK;EAC1B,aAAU;CACX,CAAA;AAEL;AAGA,SAAS,GAAW,EAAE,MAAM,GAAG,WAAQ,SAAM,eAA0F;CACrI,IAAM,EAAE,MAAG,OAAO,MAAc,EAAY,GACtC,IAAO,EAAO,EAAE,IAAI,GACpB,IAAO,EAAa,CAAC,GACrB,IAAQ,QAAc,EAAY,EAAO,KAAK,MAAM,CAAC,GAAG,CAAC,EAAO,KAAK,MAAM,CAAC,CAAC,GAC7E,IAAQ,EAAE,SACZ,EAAU,EAAa,EAAE,MAAM,CAAC,IAChC,IACE,EAAE,YAAY,EAAE,SAAS,UAAU,WACjC,EAAE,4BAA4B,EAAE,SAAS,KAAK,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,IACzE,EAAE,mBAAmB,IAErB,EADF,IACI,kBACA,iBAAiB;CAC3B,OACE,kBAAC,MAAD;EAAI,WAAU;EAAwC,aAAU;EAAc,aAAW,EAAE;EAA3F,UAAA;GACE,kBAAC,IAAD;IAAa;IAAM,KAAK,GAAO;IAAW;GAAO,CAAA;GACjD,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,QAAD;KAAM,WAAU;KAAmB,OAAO,EAAE;KACzC,UAAA,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,GAAG,IAAI,CAAC;IACrC,CAAA,GACN,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,EAAE,SAAS,qBAAqB,uBAAuB;KAAG,aAAU;KAChG,UAAA;IACG,CAAA,CACH;;GACL,kBAAC,GAAD;IAAQ,SAAQ;IAAQ,MAAK;IAAU,cAAY,EAAE,eAAe;IAAG,OAAO,EAAE,eAAe;IAAG,UAAU,KAAY,EAAO;IAAU,eAAe,KAAK,EAAO,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACjM,UAAA,kBAAC,GAAD;KAAe,MAAM;KAAc,aAAa;IAAI,CAAA;GAC9C,CAAA;EACN;;AAER;AAEA,SAAS,EAAW,GAAoB,GAAgC,GAAc,GAAuB;CAC3G,IAAI,EAAE,WAAW,UAAU,OAAO,EAAU,EAAE,KAAK;CACnD,IAAI,EAAE,WAAW,aAAa,OAAO,EAAc,GAAG,EAAE,QAAQ;CAChE,IAAI,EAAE,WAAW,YAAY;EAC3B,IAAM,IAAI,EAAE;EAGZ,OAFI,GAAG,SAAe,EAAU,EAAa,EAAE,MAAM,CAAC,IAClD,EAAE,cAAc,CAAC,EAAE,YAAkB,GAAG,YAAY,EAAE,SAAS,UAAU,WAAW,EAAE,4BAA4B,EAAE,SAAS,KAAK,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,IAAI,EAAE,mBAAmB,IAC5K,EAAP,IAAS,kBAAqB,iBAAiB;CACxD;CACA,OAAO,EAAE,WAAW,cAAc,EAAE,eAAe,IAAI,EAAE,eAAe;AAC1E;AAEA,SAAS,GAAS,EAAE,MAAM,GAAG,WAAQ,SAAM,aAAyF;CAClI,IAAM,EAAE,MAAG,OAAO,MAAc,EAAY,GACtC,EAAE,aAAU,GACZ,IAAO,EAAO,EAAE,KAAK,IAAI,GACzB,IAAQ,EAAW,GAAG,GAAW,GAAG,CAAI,GACxC,IAAQ,EAAE,WAAW,cAAc,EAAc,EAAE,QAAQ,IAAI,EAAE,cAAc,CAAC,EAAE,aAAa,EAAE,YAAY,WAAW,EAAE,WAAW,SAAS,UAAU;CAC9J,OACE,kBAAA,GAAA,EAAA,UAAA;EACG;EACD,kBAAC,IAAD;GAAa;GAAM,MAAM,EAAE,WAAW,eAAgB,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE;EAAa,CAAA;EACxF,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,kBAAC,QAAD;KAAM,WAAU;KAAmB,OAAO,EAAE;KACzC,UAAA,EAAE,KAAK;IACJ,CAAA;IACL,MAAU,QAAQ,kBAAC,GAAD;KAAiB;KAAO,cAAY;KAAO,WAAU;IAAY,CAAA;IACpF,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,EAAE,WAAW,WAAW,qBAAqB,uBAAuB;KAAG,aAAU;KAC7G,UAAA;IACG,CAAA;GACH;;EACL,kBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACG,EAAE,WAAW,YACZ,kBAAC,GAAD;IAAQ,SAAQ;IAAQ,MAAK;IAAU,cAAY,EAAE,cAAc;IAAG,OAAO,EAAE,cAAc;IAAG,eAAe,EAAM,MAAM,EAAE,EAAE;IAC7H,UAAA,kBAAC,GAAD;KAAe,MAAM;KAAe,aAAa;IAAI,CAAA;GAC/C,CAAA,GAEV,kBAAC,GAAD;IAAQ,SAAQ;IAAQ,MAAK;IAAU,cAAY,EAAE,eAAe;IAAG,OAAO,EAAE,eAAe;IAAG,eAAe,EAAM,OAAO,EAAE,EAAE;IAChI,UAAA,kBAAC,GAAD;KAAe,MAAM;KAAc,aAAa;IAAI,CAAA;GAC9C,CAAA,CACJ;;CACN,EAAA,CAAA;AAEN"}
@@ -18,6 +18,10 @@ export interface SortableListProps<T> {
18
18
  className?: string;
19
19
  /** Accessible name of the list. */
20
20
  label?: string;
21
+ /** The whole item is the drag handle (Space lifts and drops; Enter is left to the item). */
22
+ wholeItem?: boolean;
23
+ /** Unsortable entries after the items, in the same list (e.g. uploads in progress). */
24
+ trailing?: ReactNode;
21
25
  appearance?: ContentKitUiAppearance;
22
26
  }
23
27
  /**
@@ -26,4 +30,4 @@ export interface SortableListProps<T> {
26
30
  * or Enter drops, Escape cancels), with localized screen reader
27
31
  * announcements. onMove gets the old and new index once, on drop.
28
32
  */
29
- export declare function SortableList<T>({ items, id, name, onMove, layout, disabled, row, children, className, label, appearance }: SortableListProps<T>): import('react').JSX.Element;
33
+ export declare function SortableList<T>({ items, id, name, onMove, layout, disabled, row, children, className, label, appearance, wholeItem, trailing }: SortableListProps<T>): import('react').JSX.Element;
@@ -1,121 +1,137 @@
1
1
  import { useMessages as e } from "../i18n/context.js";
2
2
  import { ContentKitUiRoot as t } from "../scope.js";
3
- import { useMemo as n, useState as r } from "react";
4
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
- import { cn as o } from "cn";
6
- import { DragDropVerticalIcon as s } from "@hugeicons/core-free-icons";
7
- import { HugeiconsIcon as c } from "@hugeicons/react";
8
- import { DndContext as l, DragOverlay as u, KeyboardSensor as d, PointerSensor as f, closestCenter as p, useSensor as m, useSensors as h } from "@dnd-kit/core";
9
- import { SortableContext as g, sortableKeyboardCoordinates as _, useSortable as v } from "@dnd-kit/sortable";
3
+ import { Fragment as n, useMemo as r, useState as i } from "react";
4
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ import { cn as s } from "cn";
6
+ import { DragDropVerticalIcon as c } from "@hugeicons/core-free-icons";
7
+ import { HugeiconsIcon as l } from "@hugeicons/react";
8
+ import { DndContext as u, DragOverlay as d, KeyboardSensor as f, PointerSensor as p, closestCenter as m, useSensor as h, useSensors as g } from "@dnd-kit/core";
9
+ import { SortableContext as _, sortableKeyboardCoordinates as v, useSortable as y } from "@dnd-kit/sortable";
10
10
  //#region src/components/sortable-list.tsx
11
- var y = () => null, b = "inline-flex size-8 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing disabled:cursor-default disabled:opacity-50";
12
- function x({ items: v, id: x, name: C, onMove: w, layout: T = "list", disabled: E, row: D, children: O, className: k, label: A, appearance: j }) {
13
- let { t: M } = e(), N = h(m(f, { activationConstraint: { distance: 4 } }), m(d, { coordinateGetter: _ })), P = n(() => v.map(x), [v, x]), [F, I] = r(null), [L, R] = r(null), z = (e) => P.indexOf(String(e)), B = (e) => {
14
- let t = z(e);
15
- return t < 0 ? "" : C(v[t]);
16
- }, V = P.length, H = {
17
- onDragStart: ({ active: e }) => M("sortable.pickedUp", {
18
- name: B(e.id),
19
- position: z(e.id) + 1,
20
- total: V
11
+ var b = {
12
+ start: ["Space"],
13
+ cancel: ["Escape"],
14
+ end: ["Space"]
15
+ }, x = () => null, S = "inline-flex size-8 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing disabled:cursor-default disabled:opacity-50";
16
+ function C({ items: y, id: C, name: T, onMove: E, layout: D = "list", disabled: O, row: k, children: A, className: j, label: M, appearance: N, wholeItem: P, trailing: F }) {
17
+ let { t: I } = e(), L = g(h(p, { activationConstraint: { distance: 4 } }), h(f, {
18
+ coordinateGetter: v,
19
+ ...P ? { keyboardCodes: b } : {}
20
+ })), R = r(() => y.map(C), [y, C]), [z, B] = i(null), [V, H] = i(null), U = (e) => R.indexOf(String(e)), W = (e) => {
21
+ let t = U(e);
22
+ return t < 0 ? "" : T(y[t]);
23
+ }, G = R.length, K = {
24
+ onDragStart: ({ active: e }) => I("sortable.pickedUp", {
25
+ name: W(e.id),
26
+ position: U(e.id) + 1,
27
+ total: G
21
28
  }),
22
- onDragOver: ({ active: e, over: t }) => t ? M("sortable.over", {
23
- name: B(e.id),
24
- position: z(t.id) + 1,
25
- total: V
29
+ onDragOver: ({ active: e, over: t }) => t ? I("sortable.over", {
30
+ name: W(e.id),
31
+ position: U(t.id) + 1,
32
+ total: G
26
33
  }) : void 0,
27
- onDragEnd: ({ active: e, over: t }) => t ? M("sortable.dropped", {
28
- name: B(e.id),
29
- position: z(t.id) + 1,
30
- total: V
31
- }) : M("sortable.droppedAway", { name: B(e.id) }),
32
- onDragCancel: ({ active: e }) => M("sortable.canceled", { name: B(e.id) })
33
- }, U = { draggable: M("sortable.instructions") }, W = F ? z(F) : -1, G = L ? z(L) : -1, K = W >= 0 ? v[W] : void 0, q = T === "grid", J = (e, t) => /* @__PURE__ */ i("ol", {
34
- className: o(q ? "grid grid-cols-[repeat(auto-fill,minmax(8rem,1fr))] gap-2" : "grid gap-1", k),
35
- "aria-label": t ? void 0 : A,
34
+ onDragEnd: ({ active: e, over: t }) => t ? I("sortable.dropped", {
35
+ name: W(e.id),
36
+ position: U(t.id) + 1,
37
+ total: G
38
+ }) : I("sortable.droppedAway", { name: W(e.id) }),
39
+ onDragCancel: ({ active: e }) => I("sortable.canceled", { name: W(e.id) })
40
+ }, q = { draggable: I(P ? "sortable.instructionsTile" : "sortable.instructions") }, J = z ? U(z) : -1, Y = V ? U(V) : -1, X = J >= 0 ? y[J] : void 0, Z = D === "grid", Q = (e, t) => /* @__PURE__ */ a("ol", {
41
+ className: s(Z ? "grid grid-cols-[repeat(auto-fill,minmax(8rem,1fr))] gap-2" : "grid gap-1", j),
42
+ "aria-label": t ? void 0 : M,
36
43
  "data-ckui": "sortable-list",
37
- "data-layout": T,
44
+ "data-layout": D,
38
45
  "data-overlay": t ? "" : void 0,
39
46
  children: e
40
47
  });
41
- return /* @__PURE__ */ i(t, {
42
- appearance: j,
48
+ return /* @__PURE__ */ a(t, {
49
+ appearance: N,
43
50
  className: "contents",
44
- children: /* @__PURE__ */ a(l, {
45
- sensors: N,
46
- collisionDetection: p,
51
+ children: /* @__PURE__ */ o(u, {
52
+ sensors: L,
53
+ collisionDetection: m,
47
54
  accessibility: {
48
- announcements: H,
49
- screenReaderInstructions: U
55
+ announcements: K,
56
+ screenReaderInstructions: q
50
57
  },
51
- onDragStart: (e) => I(String(e.active.id)),
52
- onDragOver: (e) => R(e.over ? String(e.over.id) : null),
58
+ onDragStart: (e) => B(String(e.active.id)),
59
+ onDragOver: (e) => H(e.over ? String(e.over.id) : null),
53
60
  onDragCancel: () => {
54
- I(null), R(null);
61
+ B(null), H(null);
55
62
  },
56
63
  onDragEnd: (e) => {
57
- I(null), R(null);
58
- let t = z(e.active.id), n = e.over ? z(e.over.id) : -1;
59
- t >= 0 && n >= 0 && t !== n && w(t, n);
64
+ B(null), H(null);
65
+ let t = U(e.active.id), n = e.over ? U(e.over.id) : -1;
66
+ t >= 0 && n >= 0 && t !== n && E(t, n);
60
67
  },
61
- children: [/* @__PURE__ */ i(g, {
62
- items: P,
63
- strategy: y,
64
- disabled: E,
65
- children: J(v.map((e, t) => /* @__PURE__ */ i(S, {
66
- id: P[t],
67
- label: M("sortable.handle", { name: C(e) }),
68
- attrs: D?.(e),
69
- disabled: E,
70
- grid: q,
71
- dragging: t === W,
72
- drop: W >= 0 && t === G && G !== W ? G > W ? "after" : "before" : void 0,
73
- render: (n) => O(e, n, t)
74
- }, P[t])))
75
- }), /* @__PURE__ */ i(u, {
68
+ children: [/* @__PURE__ */ a(_, {
69
+ items: R,
70
+ strategy: x,
71
+ disabled: O,
72
+ children: Q(y.map((e, t) => /* @__PURE__ */ a(w, {
73
+ id: R[t],
74
+ label: I("sortable.handle", { name: T(e) }),
75
+ attrs: k?.(e),
76
+ disabled: O,
77
+ grid: Z,
78
+ whole: P,
79
+ dragging: t === J,
80
+ drop: J >= 0 && t === Y && Y !== J ? Y > J ? "after" : "before" : void 0,
81
+ render: (n) => A(e, n, t)
82
+ }, R[t])).concat(F ? [/* @__PURE__ */ a(n, { children: F }, "trailing")] : []))
83
+ }), /* @__PURE__ */ a(d, {
76
84
  dropAnimation: null,
77
- children: K === void 0 ? null : J(/* @__PURE__ */ i("li", {
78
- ...D?.(K),
79
- className: o(D?.(K).className, "cursor-grabbing rounded-md bg-background shadow-lg ring-1 ring-border"),
80
- children: O(K, /* @__PURE__ */ i("span", {
81
- className: b,
82
- children: /* @__PURE__ */ i(c, {
83
- icon: s,
85
+ children: X === void 0 ? null : Q(/* @__PURE__ */ a("li", {
86
+ ...k?.(X),
87
+ className: s(k?.(X).className, "cursor-grabbing rounded-md bg-background shadow-lg ring-1 ring-border"),
88
+ children: A(X, P ? null : /* @__PURE__ */ a("span", {
89
+ className: S,
90
+ children: /* @__PURE__ */ a(l, {
91
+ icon: c,
84
92
  strokeWidth: 2,
85
93
  className: "size-4.5"
86
94
  })
87
- }), W)
95
+ }), J)
88
96
  }), !0)
89
97
  })]
90
98
  })
91
99
  });
92
100
  }
93
- function S({ id: e, label: t, attrs: n, disabled: r, grid: a, dragging: l, drop: u, render: d }) {
94
- let { attributes: f, listeners: p, setNodeRef: m, setActivatorNodeRef: h } = v({ id: e }), g = /* @__PURE__ */ i("button", {
101
+ function w({ id: e, label: t, attrs: n, disabled: r, grid: i, whole: o, dragging: u, drop: d, render: f }) {
102
+ let { attributes: p, listeners: m, setNodeRef: h, setActivatorNodeRef: g } = y({ id: e }), _ = o ? null : /* @__PURE__ */ a("button", {
95
103
  type: "button",
96
- ref: h,
97
- className: b,
104
+ ref: g,
105
+ className: S,
98
106
  "aria-label": t,
99
107
  disabled: r,
100
108
  "data-ckui": "sort-handle",
101
- ...f,
102
109
  ...p,
103
- children: /* @__PURE__ */ i(c, {
104
- icon: s,
110
+ ...m,
111
+ children: /* @__PURE__ */ a(l, {
112
+ icon: c,
105
113
  strokeWidth: 2,
106
114
  className: "size-4.5"
107
115
  })
108
116
  });
109
- return /* @__PURE__ */ i("li", {
117
+ return /* @__PURE__ */ a("li", {
110
118
  ...n,
111
- ref: m,
112
- className: o(n?.className, "relative data-dragging:opacity-40 before:pointer-events-none before:absolute before:rounded-full before:bg-primary before:opacity-0", a ? "before:inset-y-0 before:w-0.5 data-[drop=before]:before:-left-[5px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-right-[5px] data-[drop=after]:before:opacity-100" : "before:inset-x-0 before:h-0.5 data-[drop=before]:before:-top-[3px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-bottom-[3px] data-[drop=after]:before:opacity-100"),
113
- "data-drop": u,
114
- "data-dragging": l || void 0,
115
- children: d(g)
119
+ ...o && !r ? {
120
+ ...p,
121
+ ...m,
122
+ onKeyDown: (e) => {
123
+ m?.onKeyDown?.(e), n?.onKeyDown?.(e);
124
+ },
125
+ "aria-label": t
126
+ } : {},
127
+ ref: h,
128
+ className: s(n?.className, "relative data-dragging:opacity-40 before:pointer-events-none before:absolute before:rounded-full before:bg-primary before:opacity-0", i ? "before:inset-y-0 before:w-0.5 data-[drop=before]:before:-left-[5px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-right-[5px] data-[drop=after]:before:opacity-100" : "before:inset-x-0 before:h-0.5 data-[drop=before]:before:-top-[3px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-bottom-[3px] data-[drop=after]:before:opacity-100"),
129
+ "data-drop": d,
130
+ "data-dragging": u || void 0,
131
+ children: f(_)
116
132
  });
117
133
  }
118
134
  //#endregion
119
- export { x as SortableList };
135
+ export { C as SortableList };
120
136
 
121
137
  //# sourceMappingURL=sortable-list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sortable-list.js","names":[],"sources":["../../src/components/sortable-list.tsx"],"sourcesContent":["import {\n DndContext,\n DragOverlay,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n type Announcements,\n type ScreenReaderInstructions,\n} from \"@dnd-kit/core\";\nimport { SortableContext, sortableKeyboardCoordinates, useSortable } from \"@dnd-kit/sortable\";\nimport { DragDropVerticalIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useMemo, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\n\nexport interface SortableListProps<T> {\n items: readonly T[];\n /** A stable key per item. */\n id: (item: T) => string;\n /** The item's spoken name in announcements and the handle's label. */\n name: (item: T) => string;\n /** Called once per drop with the old and new index. */\n onMove: (from: number, to: number) => void;\n /** Rows (default) or a wrapping grid of tiles. */\n layout?: \"list\" | \"grid\";\n disabled?: boolean;\n /** Attributes of an item's `<li>`. */\n row?: (item: T) => HTMLAttributes<HTMLLIElement> & Record<`data-${string}`, unknown>;\n /** An item's content; place `handle` (its drag handle) where it belongs. */\n children: (item: T, handle: ReactNode, index: number) => ReactNode;\n className?: string;\n /** Accessible name of the list. */\n label?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n// Items stay put while dragging; a bar marks where the item will land.\nconst noShift = () => null;\nconst handleClass =\n \"inline-flex size-8 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing disabled:cursor-default disabled:opacity-50\";\n\n/**\n * A reorderable list or grid (dnd-kit): drag an item by its handle with a\n * mouse, a finger or the keyboard (Space or Enter lifts, arrows move, Space\n * or Enter drops, Escape cancels), with localized screen reader\n * announcements. onMove gets the old and new index once, on drop.\n */\nexport function SortableList<T>({ items, id, name, onMove, layout = \"list\", disabled, row, children, className, label, appearance }: SortableListProps<T>) {\n const { t } = useMessages();\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));\n const ids = useMemo(() => items.map(id), [items, id]);\n const [active, setActive] = useState<string | null>(null);\n const [over, setOver] = useState<string | null>(null);\n const at = (key: unknown) => ids.indexOf(String(key));\n const spoken = (key: unknown) => {\n const i = at(key);\n return i < 0 ? \"\" : name(items[i]!);\n };\n const total = ids.length;\n const announcements: Announcements = {\n onDragStart: ({ active }) => t(\"sortable.pickedUp\", { name: spoken(active.id), position: at(active.id) + 1, total }),\n onDragOver: ({ active, over }) => (over ? t(\"sortable.over\", { name: spoken(active.id), position: at(over.id) + 1, total }) : undefined),\n onDragEnd: ({ active, over }) =>\n over ? t(\"sortable.dropped\", { name: spoken(active.id), position: at(over.id) + 1, total }) : t(\"sortable.droppedAway\", { name: spoken(active.id) }),\n onDragCancel: ({ active }) => t(\"sortable.canceled\", { name: spoken(active.id) }),\n };\n const instructions: ScreenReaderInstructions = { draggable: t(\"sortable.instructions\") };\n const from = active ? at(active) : -1;\n const to = over ? at(over) : -1;\n const dragged = from >= 0 ? items[from] : undefined;\n const grid = layout === \"grid\";\n const list = (inner: ReactNode, overlay?: boolean) => (\n <ol\n className={cn(grid ? \"grid grid-cols-[repeat(auto-fill,minmax(8rem,1fr))] gap-2\" : \"grid gap-1\", className)}\n aria-label={overlay ? undefined : label}\n data-ckui=\"sortable-list\"\n data-layout={layout}\n data-overlay={overlay ? \"\" : undefined}\n >\n {inner}\n </ol>\n );\n return (\n <ContentKitUiRoot appearance={appearance} className=\"contents\">\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n accessibility={{ announcements, screenReaderInstructions: instructions }}\n onDragStart={(e) => setActive(String(e.active.id))}\n onDragOver={(e) => setOver(e.over ? String(e.over.id) : null)}\n onDragCancel={() => {\n setActive(null);\n setOver(null);\n }}\n onDragEnd={(e) => {\n setActive(null);\n setOver(null);\n const a = at(e.active.id);\n const b = e.over ? at(e.over.id) : -1;\n if (a >= 0 && b >= 0 && a !== b) onMove(a, b);\n }}\n >\n <SortableContext items={ids} strategy={noShift} disabled={disabled}>\n {list(\n items.map((item, i) => (\n <Item\n key={ids[i]}\n id={ids[i]!}\n label={t(\"sortable.handle\", { name: name(item) })}\n attrs={row?.(item)}\n disabled={disabled}\n grid={grid}\n dragging={i === from}\n drop={from >= 0 && i === to && to !== from ? (to > from ? \"after\" : \"before\") : undefined}\n render={(handle) => children(item, handle, i)}\n />\n )),\n )}\n </SortableContext>\n <DragOverlay dropAnimation={null}>\n {dragged !== undefined\n ? list(\n <li {...row?.(dragged)} className={cn(row?.(dragged).className, \"cursor-grabbing rounded-md bg-background shadow-lg ring-1 ring-border\")}>\n {children(\n dragged,\n <span className={handleClass}>\n <HugeiconsIcon icon={DragDropVerticalIcon} strokeWidth={2} className=\"size-4.5\" />\n </span>,\n from,\n )}\n </li>,\n true,\n )\n : null}\n </DragOverlay>\n </DndContext>\n </ContentKitUiRoot>\n );\n}\n\nfunction Item({\n id,\n label,\n attrs,\n disabled,\n grid,\n dragging,\n drop,\n render,\n}: {\n id: string;\n label: string;\n attrs?: HTMLAttributes<HTMLLIElement>;\n disabled?: boolean;\n grid: boolean;\n dragging: boolean;\n drop?: \"before\" | \"after\";\n render: (handle: ReactNode) => ReactNode;\n}) {\n const { attributes, listeners, setNodeRef, setActivatorNodeRef } = useSortable({ id });\n const handle = (\n <button type=\"button\" ref={setActivatorNodeRef} className={handleClass} aria-label={label} disabled={disabled} data-ckui=\"sort-handle\" {...attributes} {...listeners}>\n <HugeiconsIcon icon={DragDropVerticalIcon} strokeWidth={2} className=\"size-4.5\" />\n </button>\n );\n return (\n <li\n {...attrs}\n ref={setNodeRef}\n className={cn(\n attrs?.className,\n \"relative data-dragging:opacity-40 before:pointer-events-none before:absolute before:rounded-full before:bg-primary before:opacity-0\",\n grid\n ? \"before:inset-y-0 before:w-0.5 data-[drop=before]:before:-left-[5px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-right-[5px] data-[drop=after]:before:opacity-100\"\n : \"before:inset-x-0 before:h-0.5 data-[drop=before]:before:-top-[3px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-bottom-[3px] data-[drop=after]:before:opacity-100\",\n )}\n data-drop={drop}\n data-dragging={dragging || undefined}\n >\n {render(handle)}\n </li>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sortable-list.js","names":[],"sources":["../../src/components/sortable-list.tsx"],"sourcesContent":["import {\n DndContext,\n DragOverlay,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n type Announcements,\n type ScreenReaderInstructions,\n} from \"@dnd-kit/core\";\nimport { SortableContext, sortableKeyboardCoordinates, useSortable } from \"@dnd-kit/sortable\";\nimport { DragDropVerticalIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { Fragment, useMemo, useState, type HTMLAttributes, type KeyboardEvent, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\n\nexport interface SortableListProps<T> {\n items: readonly T[];\n /** A stable key per item. */\n id: (item: T) => string;\n /** The item's spoken name in announcements and the handle's label. */\n name: (item: T) => string;\n /** Called once per drop with the old and new index. */\n onMove: (from: number, to: number) => void;\n /** Rows (default) or a wrapping grid of tiles. */\n layout?: \"list\" | \"grid\";\n disabled?: boolean;\n /** Attributes of an item's `<li>`. */\n row?: (item: T) => HTMLAttributes<HTMLLIElement> & Record<`data-${string}`, unknown>;\n /** An item's content; place `handle` (its drag handle) where it belongs. */\n children: (item: T, handle: ReactNode, index: number) => ReactNode;\n className?: string;\n /** Accessible name of the list. */\n label?: string;\n /** The whole item is the drag handle (Space lifts and drops; Enter is left to the item). */\n wholeItem?: boolean;\n /** Unsortable entries after the items, in the same list (e.g. uploads in progress). */\n trailing?: ReactNode;\n appearance?: ContentKitUiAppearance;\n}\n\nconst SPACE_ONLY = { start: [\"Space\"], cancel: [\"Escape\"], end: [\"Space\"] };\n\n// Items stay put while dragging; a bar marks where the item will land.\nconst noShift = () => null;\nconst handleClass =\n \"inline-flex size-8 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing disabled:cursor-default disabled:opacity-50\";\n\n/**\n * A reorderable list or grid (dnd-kit): drag an item by its handle with a\n * mouse, a finger or the keyboard (Space or Enter lifts, arrows move, Space\n * or Enter drops, Escape cancels), with localized screen reader\n * announcements. onMove gets the old and new index once, on drop.\n */\nexport function SortableList<T>({ items, id, name, onMove, layout = \"list\", disabled, row, children, className, label, appearance, wholeItem, trailing }: SortableListProps<T>) {\n const { t } = useMessages();\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, ...(wholeItem ? { keyboardCodes: SPACE_ONLY } : {}) }),\n );\n const ids = useMemo(() => items.map(id), [items, id]);\n const [active, setActive] = useState<string | null>(null);\n const [over, setOver] = useState<string | null>(null);\n const at = (key: unknown) => ids.indexOf(String(key));\n const spoken = (key: unknown) => {\n const i = at(key);\n return i < 0 ? \"\" : name(items[i]!);\n };\n const total = ids.length;\n const announcements: Announcements = {\n onDragStart: ({ active }) => t(\"sortable.pickedUp\", { name: spoken(active.id), position: at(active.id) + 1, total }),\n onDragOver: ({ active, over }) => (over ? t(\"sortable.over\", { name: spoken(active.id), position: at(over.id) + 1, total }) : undefined),\n onDragEnd: ({ active, over }) =>\n over ? t(\"sortable.dropped\", { name: spoken(active.id), position: at(over.id) + 1, total }) : t(\"sortable.droppedAway\", { name: spoken(active.id) }),\n onDragCancel: ({ active }) => t(\"sortable.canceled\", { name: spoken(active.id) }),\n };\n const instructions: ScreenReaderInstructions = { draggable: t(wholeItem ? \"sortable.instructionsTile\" : \"sortable.instructions\") };\n const from = active ? at(active) : -1;\n const to = over ? at(over) : -1;\n const dragged = from >= 0 ? items[from] : undefined;\n const grid = layout === \"grid\";\n const list = (inner: ReactNode, overlay?: boolean) => (\n <ol\n className={cn(grid ? \"grid grid-cols-[repeat(auto-fill,minmax(8rem,1fr))] gap-2\" : \"grid gap-1\", className)}\n aria-label={overlay ? undefined : label}\n data-ckui=\"sortable-list\"\n data-layout={layout}\n data-overlay={overlay ? \"\" : undefined}\n >\n {inner}\n </ol>\n );\n return (\n <ContentKitUiRoot appearance={appearance} className=\"contents\">\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n accessibility={{ announcements, screenReaderInstructions: instructions }}\n onDragStart={(e) => setActive(String(e.active.id))}\n onDragOver={(e) => setOver(e.over ? String(e.over.id) : null)}\n onDragCancel={() => {\n setActive(null);\n setOver(null);\n }}\n onDragEnd={(e) => {\n setActive(null);\n setOver(null);\n const a = at(e.active.id);\n const b = e.over ? at(e.over.id) : -1;\n if (a >= 0 && b >= 0 && a !== b) onMove(a, b);\n }}\n >\n <SortableContext items={ids} strategy={noShift} disabled={disabled}>\n {list(\n items.map((item, i) => (\n <Item\n key={ids[i]}\n id={ids[i]!}\n label={t(\"sortable.handle\", { name: name(item) })}\n attrs={row?.(item)}\n disabled={disabled}\n grid={grid}\n whole={wholeItem}\n dragging={i === from}\n drop={from >= 0 && i === to && to !== from ? (to > from ? \"after\" : \"before\") : undefined}\n render={(handle) => children(item, handle, i)}\n />\n )).concat(trailing ? [<Fragment key=\"trailing\">{trailing}</Fragment>] : []),\n )}\n </SortableContext>\n <DragOverlay dropAnimation={null}>\n {dragged !== undefined\n ? list(\n <li {...row?.(dragged)} className={cn(row?.(dragged).className, \"cursor-grabbing rounded-md bg-background shadow-lg ring-1 ring-border\")}>\n {children(\n dragged,\n wholeItem ? null : (\n <span className={handleClass}>\n <HugeiconsIcon icon={DragDropVerticalIcon} strokeWidth={2} className=\"size-4.5\" />\n </span>\n ),\n from,\n )}\n </li>,\n true,\n )\n : null}\n </DragOverlay>\n </DndContext>\n </ContentKitUiRoot>\n );\n}\n\nfunction Item({\n id,\n label,\n attrs,\n disabled,\n grid,\n whole,\n dragging,\n drop,\n render,\n}: {\n id: string;\n label: string;\n attrs?: HTMLAttributes<HTMLLIElement>;\n disabled?: boolean;\n grid: boolean;\n whole?: boolean;\n dragging: boolean;\n drop?: \"before\" | \"after\";\n render: (handle: ReactNode) => ReactNode;\n}) {\n const { attributes, listeners, setNodeRef, setActivatorNodeRef } = useSortable({ id });\n const handle = whole ? null : (\n <button type=\"button\" ref={setActivatorNodeRef} className={handleClass} aria-label={label} disabled={disabled} data-ckui=\"sort-handle\" {...attributes} {...listeners}>\n <HugeiconsIcon icon={DragDropVerticalIcon} strokeWidth={2} className=\"size-4.5\" />\n </button>\n );\n return (\n <li\n {...attrs}\n {...(whole && !disabled\n ? {\n ...attributes,\n ...listeners,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n listeners?.onKeyDown?.(e);\n attrs?.onKeyDown?.(e);\n },\n \"aria-label\": label,\n }\n : {})}\n ref={setNodeRef}\n className={cn(\n attrs?.className,\n \"relative data-dragging:opacity-40 before:pointer-events-none before:absolute before:rounded-full before:bg-primary before:opacity-0\",\n grid\n ? \"before:inset-y-0 before:w-0.5 data-[drop=before]:before:-left-[5px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-right-[5px] data-[drop=after]:before:opacity-100\"\n : \"before:inset-x-0 before:h-0.5 data-[drop=before]:before:-top-[3px] data-[drop=before]:before:opacity-100 data-[drop=after]:before:-bottom-[3px] data-[drop=after]:before:opacity-100\",\n )}\n data-drop={drop}\n data-dragging={dragging || undefined}\n >\n {render(handle)}\n </li>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { CSSProperties } from 'react';
2
2
  import { ContentKitUiAppearance } from '../appearance.js';
3
3
  import { HlsPlayerOptions } from '../react/gallery.js';
4
+ import { ReadingEngagement } from '../react/use-engagement.js';
4
5
  import { PlaybackProgress } from '../react/player.js';
5
6
  import { PlayerHandoff } from './video-player.js';
6
7
  export interface VideoMiniPlayerProps extends Omit<HlsPlayerOptions, "src" | "startAt" | "autoPlay" | "audioLanguage" | "subtitleLanguage" | "active"> {
@@ -15,6 +16,8 @@ export interface VideoMiniPlayerProps extends Omit<HlsPlayerOptions, "src" | "st
15
16
  time: number;
16
17
  }) => void;
17
18
  onProgress?: (progress: PlaybackProgress) => void;
19
+ /** Continue actual visible playback measurements after the full player handoff. */
20
+ engagement?: Pick<ReadingEngagement, "video">;
18
21
  /** Milliseconds. Default 10000. */
19
22
  progressInterval?: number;
20
23
  /** K, J, L and M page-wide (default), every shortcut while focus is in it, or none. */
@@ -32,4 +35,4 @@ export interface VideoMiniPlayerProps extends Omit<HlsPlayerOptions, "src" | "st
32
35
  * a seek line, expand back to the full player and close. It starts where
33
36
  * the handoff stopped, playing if it was.
34
37
  */
35
- export declare function VideoMiniPlayer({ handoff, onExpand, onClose, onProgress, progressInterval, keyboard, label, position, crossOrigin, className, style, appearance, ...options }: VideoMiniPlayerProps): import('react').JSX.Element;
38
+ export declare function VideoMiniPlayer({ handoff, onExpand, onClose, onProgress, engagement, progressInterval, keyboard, label, position, crossOrigin, className, style, appearance, ...options }: VideoMiniPlayerProps): import('react').JSX.Element;