@k2b/ui 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +3 -2
  2. package/dist/browser/actions/ContextMenu.js +3 -1
  3. package/dist/browser/actions/ContextMenu.js.map +1 -1
  4. package/dist/browser/actions/Dropdown.js +91 -46
  5. package/dist/browser/actions/Dropdown.js.map +1 -1
  6. package/dist/browser/actions/FilterChip.js +4 -1
  7. package/dist/browser/actions/FilterChip.js.map +1 -1
  8. package/dist/browser/actions/GestureMenu.js +467 -0
  9. package/dist/browser/actions/GestureMenu.js.map +1 -0
  10. package/dist/browser/actions/index.js +1 -0
  11. package/dist/browser/actions/index.js.map +1 -1
  12. package/dist/browser/chat/ChatComposer.js +1255 -534
  13. package/dist/browser/chat/ChatComposer.js.map +1 -1
  14. package/dist/browser/chat/ChatPrimitives.js +9 -3
  15. package/dist/browser/chat/ChatPrimitives.js.map +1 -1
  16. package/dist/browser/chat/ChatTimeline.js +19 -1
  17. package/dist/browser/chat/ChatTimeline.js.map +1 -1
  18. package/dist/browser/chat/chat-behavior.js +9 -0
  19. package/dist/browser/chat/chat-behavior.js.map +1 -1
  20. package/dist/browser/chat/index.js.map +1 -1
  21. package/dist/browser/chat/types.js.map +1 -1
  22. package/dist/browser/content/Calendar.js +579 -533
  23. package/dist/browser/content/Calendar.js.map +1 -1
  24. package/dist/browser/content/Lightbox.js +76 -40
  25. package/dist/browser/content/Lightbox.js.map +1 -1
  26. package/dist/browser/content/MessageRow.js +2 -2
  27. package/dist/browser/content/MessageRow.js.map +1 -1
  28. package/dist/browser/content/PdfPreview.js +146 -79
  29. package/dist/browser/content/PdfPreview.js.map +1 -1
  30. package/dist/browser/content/Timeline.js +1038 -0
  31. package/dist/browser/content/Timeline.js.map +1 -0
  32. package/dist/browser/content/VideoPlayer.js +29 -9
  33. package/dist/browser/content/VideoPlayer.js.map +1 -1
  34. package/dist/browser/content/chart-inspection.js +7 -2
  35. package/dist/browser/content/chart-inspection.js.map +1 -1
  36. package/dist/browser/content/index.js +1 -0
  37. package/dist/browser/content/index.js.map +1 -1
  38. package/dist/browser/content/timeline-model.js +579 -0
  39. package/dist/browser/content/timeline-model.js.map +1 -0
  40. package/dist/browser/feedback/dialog-core.js +26 -14
  41. package/dist/browser/feedback/dialog-core.js.map +1 -1
  42. package/dist/browser/inputs/ChoiceChips.js +66 -0
  43. package/dist/browser/inputs/ChoiceChips.js.map +1 -0
  44. package/dist/browser/inputs/ChoiceGroups.js +53 -12
  45. package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
  46. package/dist/browser/inputs/FileInputs.js +48 -33
  47. package/dist/browser/inputs/FileInputs.js.map +1 -1
  48. package/dist/browser/inputs/SignatureInput.js +558 -0
  49. package/dist/browser/inputs/SignatureInput.js.map +1 -0
  50. package/dist/browser/inputs/TextInput.js +13 -1
  51. package/dist/browser/inputs/TextInput.js.map +1 -1
  52. package/dist/browser/inputs/emoji/EmojiPicker.js +841 -0
  53. package/dist/browser/inputs/emoji/EmojiPicker.js.map +1 -0
  54. package/dist/browser/inputs/emoji/emoji-data.js +1903 -0
  55. package/dist/browser/inputs/emoji/emoji-data.js.map +1 -0
  56. package/dist/browser/inputs/emoji/emoji-index.js +209 -0
  57. package/dist/browser/inputs/emoji/emoji-index.js.map +1 -0
  58. package/dist/browser/inputs/emoji/emoji-messages.js +64 -0
  59. package/dist/browser/inputs/emoji/emoji-messages.js.map +1 -0
  60. package/dist/browser/inputs/index.js +5 -0
  61. package/dist/browser/inputs/index.js.map +1 -1
  62. package/dist/browser/inputs/markdown/actions.js +6 -2
  63. package/dist/browser/inputs/markdown/actions.js.map +1 -1
  64. package/dist/browser/inputs/markdown/code-zone.js +38 -2
  65. package/dist/browser/inputs/markdown/code-zone.js.map +1 -1
  66. package/dist/browser/inputs/signature-messages.js +39 -0
  67. package/dist/browser/inputs/signature-messages.js.map +1 -0
  68. package/dist/browser/inputs/signature.js +208 -0
  69. package/dist/browser/inputs/signature.js.map +1 -0
  70. package/dist/browser/internal/render-error.js +49 -0
  71. package/dist/browser/internal/render-error.js.map +1 -0
  72. package/dist/browser/intl/messages.js +102 -0
  73. package/dist/browser/intl/messages.js.map +1 -1
  74. package/dist/browser/layout/AppWorkspace.js +321 -222
  75. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  76. package/dist/browser/layout/FloatingWindow.js +4 -1
  77. package/dist/browser/layout/FloatingWindow.js.map +1 -1
  78. package/dist/browser/layout/SidebarItemPreview.js +5 -1
  79. package/dist/browser/layout/SidebarItemPreview.js.map +1 -1
  80. package/dist/browser/layout/index.js.map +1 -1
  81. package/dist/browser/surfaces/ResourceCard.js +212 -0
  82. package/dist/browser/surfaces/ResourceCard.js.map +1 -0
  83. package/dist/browser/surfaces/index.js +1 -0
  84. package/dist/browser/surfaces/index.js.map +1 -1
  85. package/dist/licenses/emojibase-data.txt +21 -0
  86. package/dist/ssr/actions/ContextMenu.js +3 -1
  87. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  88. package/dist/ssr/actions/Dropdown.js +49 -12
  89. package/dist/ssr/actions/Dropdown.js.map +1 -1
  90. package/dist/ssr/actions/FilterChip.js +4 -1
  91. package/dist/ssr/actions/FilterChip.js.map +1 -1
  92. package/dist/ssr/actions/GestureMenu.js +411 -0
  93. package/dist/ssr/actions/GestureMenu.js.map +1 -0
  94. package/dist/ssr/actions/index.js +1 -0
  95. package/dist/ssr/actions/index.js.map +1 -1
  96. package/dist/ssr/chat/ChatComposer.js +767 -214
  97. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  98. package/dist/ssr/chat/ChatPrimitives.js +9 -3
  99. package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
  100. package/dist/ssr/chat/ChatTimeline.js +19 -1
  101. package/dist/ssr/chat/ChatTimeline.js.map +1 -1
  102. package/dist/ssr/chat/chat-behavior.js +9 -0
  103. package/dist/ssr/chat/chat-behavior.js.map +1 -1
  104. package/dist/ssr/chat/index.js.map +1 -1
  105. package/dist/ssr/chat/types.js.map +1 -1
  106. package/dist/ssr/content/Calendar.js +183 -142
  107. package/dist/ssr/content/Calendar.js.map +1 -1
  108. package/dist/ssr/content/Lightbox.js +19 -5
  109. package/dist/ssr/content/Lightbox.js.map +1 -1
  110. package/dist/ssr/content/MessageRow.js +2 -2
  111. package/dist/ssr/content/MessageRow.js.map +1 -1
  112. package/dist/ssr/content/PdfPreview.js +77 -36
  113. package/dist/ssr/content/PdfPreview.js.map +1 -1
  114. package/dist/ssr/content/Timeline.js +804 -0
  115. package/dist/ssr/content/Timeline.js.map +1 -0
  116. package/dist/ssr/content/VideoPlayer.js +29 -9
  117. package/dist/ssr/content/VideoPlayer.js.map +1 -1
  118. package/dist/ssr/content/chart-inspection.js +7 -2
  119. package/dist/ssr/content/chart-inspection.js.map +1 -1
  120. package/dist/ssr/content/index.js +1 -0
  121. package/dist/ssr/content/index.js.map +1 -1
  122. package/dist/ssr/content/timeline-model.js +579 -0
  123. package/dist/ssr/content/timeline-model.js.map +1 -0
  124. package/dist/ssr/feedback/dialog-core.js +26 -14
  125. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  126. package/dist/ssr/inputs/ChoiceChips.js +66 -0
  127. package/dist/ssr/inputs/ChoiceChips.js.map +1 -0
  128. package/dist/ssr/inputs/ChoiceGroups.js +12 -4
  129. package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
  130. package/dist/ssr/inputs/FileInputs.js +19 -4
  131. package/dist/ssr/inputs/FileInputs.js.map +1 -1
  132. package/dist/ssr/inputs/SignatureInput.js +404 -0
  133. package/dist/ssr/inputs/SignatureInput.js.map +1 -0
  134. package/dist/ssr/inputs/TextInput.js +13 -1
  135. package/dist/ssr/inputs/TextInput.js.map +1 -1
  136. package/dist/ssr/inputs/emoji/EmojiPicker.js +551 -0
  137. package/dist/ssr/inputs/emoji/EmojiPicker.js.map +1 -0
  138. package/dist/ssr/inputs/emoji/emoji-data.js +1903 -0
  139. package/dist/ssr/inputs/emoji/emoji-data.js.map +1 -0
  140. package/dist/ssr/inputs/emoji/emoji-index.js +209 -0
  141. package/dist/ssr/inputs/emoji/emoji-index.js.map +1 -0
  142. package/dist/ssr/inputs/emoji/emoji-messages.js +64 -0
  143. package/dist/ssr/inputs/emoji/emoji-messages.js.map +1 -0
  144. package/dist/ssr/inputs/index.js +5 -0
  145. package/dist/ssr/inputs/index.js.map +1 -1
  146. package/dist/ssr/inputs/markdown/actions.js +6 -2
  147. package/dist/ssr/inputs/markdown/actions.js.map +1 -1
  148. package/dist/ssr/inputs/markdown/code-zone.js +38 -2
  149. package/dist/ssr/inputs/markdown/code-zone.js.map +1 -1
  150. package/dist/ssr/inputs/signature-messages.js +39 -0
  151. package/dist/ssr/inputs/signature-messages.js.map +1 -0
  152. package/dist/ssr/inputs/signature.js +208 -0
  153. package/dist/ssr/inputs/signature.js.map +1 -0
  154. package/dist/ssr/internal/render-error.js +49 -0
  155. package/dist/ssr/internal/render-error.js.map +1 -0
  156. package/dist/ssr/intl/messages.js +102 -0
  157. package/dist/ssr/intl/messages.js.map +1 -1
  158. package/dist/ssr/layout/AppWorkspace.js +112 -41
  159. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  160. package/dist/ssr/layout/FloatingWindow.js +4 -1
  161. package/dist/ssr/layout/FloatingWindow.js.map +1 -1
  162. package/dist/ssr/layout/SidebarItemPreview.js +5 -1
  163. package/dist/ssr/layout/SidebarItemPreview.js.map +1 -1
  164. package/dist/ssr/layout/index.js.map +1 -1
  165. package/dist/ssr/surfaces/ResourceCard.js +115 -0
  166. package/dist/ssr/surfaces/ResourceCard.js.map +1 -0
  167. package/dist/ssr/surfaces/index.js +1 -0
  168. package/dist/ssr/surfaces/index.js.map +1 -1
  169. package/dist/styles.css +1 -1
  170. package/dist/types/actions/Dropdown.d.ts +13 -1
  171. package/dist/types/actions/FilterChip.d.ts +5 -0
  172. package/dist/types/actions/GestureMenu.d.ts +35 -0
  173. package/dist/types/actions/index.d.ts +2 -0
  174. package/dist/types/chat/ChatComposer.d.ts +27 -1
  175. package/dist/types/chat/chat-behavior.d.ts +15 -0
  176. package/dist/types/chat/index.d.ts +1 -1
  177. package/dist/types/chat/types.d.ts +34 -0
  178. package/dist/types/content/Calendar.d.ts +28 -8
  179. package/dist/types/content/Lightbox.d.ts +8 -0
  180. package/dist/types/content/Timeline.d.ts +49 -0
  181. package/dist/types/content/index.d.ts +4 -2
  182. package/dist/types/content/timeline-model.d.ts +148 -0
  183. package/dist/types/feedback/dialog-core.d.ts +1 -1
  184. package/dist/types/inputs/ChoiceChips.d.ts +20 -0
  185. package/dist/types/inputs/ChoiceGroups.d.ts +11 -2
  186. package/dist/types/inputs/FileInputs.d.ts +6 -0
  187. package/dist/types/inputs/SignatureInput.d.ts +22 -0
  188. package/dist/types/inputs/emoji/EmojiPicker.d.ts +42 -0
  189. package/dist/types/inputs/emoji/emoji-data.d.ts +2 -0
  190. package/dist/types/inputs/emoji/emoji-index.d.ts +109 -0
  191. package/dist/types/inputs/emoji/emoji-messages.d.ts +30 -0
  192. package/dist/types/inputs/index.d.ts +10 -0
  193. package/dist/types/inputs/markdown/actions.d.ts +2 -0
  194. package/dist/types/inputs/markdown/code-zone.d.ts +7 -0
  195. package/dist/types/inputs/signature-messages.d.ts +11 -0
  196. package/dist/types/inputs/signature.d.ts +72 -0
  197. package/dist/types/internal/render-error.d.ts +13 -0
  198. package/dist/types/intl/messages.d.ts +51 -0
  199. package/dist/types/layout/AppWorkspace.d.ts +17 -0
  200. package/dist/types/layout/SidebarItemPreview.d.ts +2 -0
  201. package/dist/types/layout/index.d.ts +1 -1
  202. package/dist/types/surfaces/ResourceCard.d.ts +31 -0
  203. package/dist/types/surfaces/index.d.ts +2 -0
  204. package/package.json +6 -5
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["inputs/FileInputs.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { Tooltip } from \"../feedback/Tooltip\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { fileDropTarget } from \"./FileDropTarget\";\nimport type { FieldProps, ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { fileDropEngine, liveDocument } from \"./file-drop\";\nimport {\n clampImageCropRect,\n getInitialImageCropRect,\n type ImageCropAspect,\n type ImageCropRect,\n type ImageCropResizeHandle,\n type ImageCropRotation,\n type ImageCropSource,\n type ImageCropState,\n resizeImageCropFromCorner,\n rotateImageCropRight,\n} from \"./image-crop\";\n\nexport type FileDropzoneProps = FieldProps & {\n accept?: string;\n multiple?: boolean;\n busy?: boolean;\n /** Full icon class list, for example `\"ti ti-photo-plus\"`. Defaults to `\"ti ti-cloud-upload\"`. */\n icon?: string;\n title?: JSX.Element;\n subtitle?: JSX.Element;\n hint?: JSX.Element;\n /** One sentence that says what dropping does, shown while files are over the zone. Defaults to \"Drop to upload\". */\n dropLabel?: string;\n onDrop: (files: File[]) => void | Promise<void>;\n};\n\nexport function FileDropzone(props: FileDropzoneProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n const disabled = () => Boolean(props.disabled || props.busy);\n const error = () => resolveMaybeAccessor(props.error);\n let input: HTMLInputElement | undefined;\n const [button, setButton] = createSignal<HTMLButtonElement>();\n const emit = (files: File[]) => {\n if (disabled() || files.length === 0) return;\n void props.onDrop(props.multiple === false ? files.slice(0, 1) : files);\n };\n // Drops take the same path as every other file drop target: files only, the most specific target wins, and files\n // that do not fit `accept` are left out with a message.\n const dropLabel = () => props.dropLabel ?? messages().dropToUpload;\n const dropRef = fileDropTarget({\n get label() {\n return dropLabel();\n },\n get accept() {\n return props.accept;\n },\n get multiple() {\n return props.multiple;\n },\n get disabled() {\n return disabled();\n },\n onDrop: emit,\n });\n const [engine, setEngine] = createSignal<ReturnType<typeof fileDropEngine>>();\n onMount(() => {\n const element = button();\n if (element) setEngine(fileDropEngine(liveDocument(element)));\n });\n const dragState = createMemo(() => {\n const element = button();\n const hover = engine()?.session()?.hover;\n if (!hover || hover.element !== element) return undefined;\n return hover.invalid ? \"invalid\" : \"over\";\n });\n const title = () =>\n props.busy\n ? messages().uploading\n : dragState() === \"invalid\"\n ? messages().fileTypeNotAccepted\n : dragState() === \"over\"\n ? dropLabel()\n : (props.title ?? messages().dropFiles);\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <button\n id={meta.controlId}\n type=\"button\"\n ref={(element) => {\n setButton(element);\n dropRef(element);\n }}\n class=\"k2b-dropzone\"\n data-invalid={error() ? \"true\" : undefined}\n disabled={disabled()}\n {...fieldControlAria(meta, props)}\n onClick={() => input?.click()}\n >\n <span class=\"k2b-dropzone__icon\" aria-hidden=\"true\">\n <i class={props.busy ? \"ti ti-loader-2 k2b-spin\" : (props.icon ?? \"ti ti-cloud-upload\")} />\n </span>\n <span class=\"k2b-dropzone__copy\">\n <strong>{title()}</strong>\n <Show\n when={dragState() === \"invalid\"}\n fallback={\n <Show when={props.subtitle}>\n <span class=\"k2b-dropzone__subtitle\">{props.subtitle}</span>\n </Show>\n }\n >\n <span class=\"k2b-dropzone__subtitle\">{messages().chooseMatchingFile}</span>\n </Show>\n <Show when={props.hint}>\n <span class=\"k2b-dropzone__hint\">{props.hint}</span>\n </Show>\n </span>\n </button>\n <input\n ref={input}\n class=\"k2b-sr-only\"\n type=\"file\"\n aria-label={\n props[\"aria-label\"] ??\n (typeof props.label === \"string\" ? props.label : props.multiple === false ? messages().chooseFile : messages().chooseFiles)\n }\n accept={props.accept}\n multiple={props.multiple ?? true}\n disabled={disabled()}\n tabIndex={-1}\n onChange={(event) => {\n const files = Array.from(event.currentTarget.files ?? []);\n // Reset before emitting so re-picking the same file still fires change,\n // even when onDrop throws.\n event.currentTarget.value = \"\";\n emit(files);\n }}\n />\n </Field>\n );\n}\n\nexport type ImageInputProps = ValueFieldProps<string | null> & {\n round?: boolean;\n variant?: \"default\" | \"small\";\n transform?: (file: File) => Promise<string>;\n accept?: string;\n fallbackMarker?: string;\n};\n\nconst DEFAULT_IMAGE_ACCEPT = \"image/jpeg,image/png,image/gif,image/webp,image/svg+xml,.jpg,.jpeg,.png,.gif,.webp,.svg\";\n\nconst defaultImageTransform = async (file: File): Promise<string> => {\n const { img } = await import(\"@k2b/stdlib/browser\");\n return img.presets.avatar(file);\n};\n\nexport function ImageInput(props: ImageInputProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n const [busy, setBusy] = createSignal(false);\n const [localError, setLocalError] = createSignal<string>();\n let input: HTMLInputElement | undefined;\n const disabled = () => Boolean(props.disabled || busy() || !props.onValueChange);\n const error = () => resolveMaybeAccessor(props.error) ?? localError();\n const value = () => {\n const current = resolveMaybeAccessor(props.value);\n return current && !current.includes(props.fallbackMarker ?? \"?fallback\") ? current : null;\n };\n const compact = () => props.variant === \"small\";\n const changeLabel = () => (value() ? messages().changeImage : messages().addImage);\n const changeIcon = () => (value() ? \"ti ti-pencil\" : \"ti ti-photo-plus\");\n const select = async (file: File | undefined) => {\n if (!file || disabled()) return;\n setBusy(true);\n setLocalError();\n try {\n const transformed = await (props.transform ?? defaultImageTransform)(file);\n commitFieldValue(props, transformed);\n } catch (error) {\n setLocalError(error instanceof Error ? error.message : messages().imageProcessingFailed);\n } finally {\n setBusy(false);\n if (input) input.value = \"\";\n }\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <div\n class=\"k2b-image-input\"\n data-round={props.round ? \"true\" : undefined}\n data-variant={props.variant ?? \"default\"}\n role=\"group\"\n aria-labelledby={props.label ? meta.labelId : undefined}\n aria-label={!props.label ? props[\"aria-label\"] : undefined}\n aria-describedby={fieldControlAria(meta, { ...props, error })[\"aria-describedby\"]}\n >\n <div class=\"k2b-image-input__preview\">\n <Show when={value()} fallback={<i class=\"ti ti-photo-off\" aria-hidden=\"true\" />}>\n {(source) => <img src={source()} alt={typeof props.label === \"string\" ? props.label : messages().selectedImage} />}\n </Show>\n </div>\n <div class=\"k2b-image-input__actions\">\n <Show\n when={compact()}\n fallback={\n <Button\n variant=\"secondary\"\n loading={busy()}\n loadingLabel={messages().processingImage}\n disabled={disabled()}\n onClick={() => input?.click()}\n >\n <i class={changeIcon()} aria-hidden=\"true\" />\n {value() ? messages().change : messages().add}\n </Button>\n }\n >\n <IconButton\n label={changeLabel()}\n loading={busy()}\n loadingLabel={messages().processingImage}\n disabled={disabled()}\n onClick={() => input?.click()}\n >\n <i class={changeIcon()} aria-hidden=\"true\" />\n </IconButton>\n </Show>\n <Show when={value()}>\n <Show\n when={compact()}\n fallback={\n <Button variant=\"ghost\" disabled={disabled()} onClick={() => commitFieldValue(props, null)}>\n <i class=\"ti ti-trash\" aria-hidden=\"true\" /> Remove\n </Button>\n }\n >\n <IconButton label={messages().removeImage} disabled={disabled()} onClick={() => commitFieldValue(props, null)}>\n <i class=\"ti ti-trash\" aria-hidden=\"true\" />\n </IconButton>\n </Show>\n </Show>\n </div>\n <input\n ref={input}\n id={meta.controlId}\n class=\"k2b-sr-only\"\n type=\"file\"\n accept={props.accept ?? DEFAULT_IMAGE_ACCEPT}\n disabled={disabled()}\n required={props.required && !value()}\n {...fieldControlAria(meta, { ...props, error })}\n onChange={(event) => void select(event.currentTarget.files?.[0])}\n />\n </div>\n </Field>\n );\n}\n\ntype PreviewState = {\n url: string;\n objectUrl: boolean;\n sourceWidth: number;\n sourceHeight: number;\n};\n\ntype DragHandle = \"move\" | ImageCropResizeHandle;\ntype DragState = {\n handle: DragHandle;\n pointerId: number;\n startX: number;\n startY: number;\n startCrop: ImageCropRect;\n};\n\nexport type ImageCropperProps = {\n source: ImageCropSource;\n aspect?: ImageCropAspect;\n previewShape?: \"rect\" | \"circle\";\n disabled?: boolean;\n onValueChange?: (state: ImageCropState | null) => void;\n class?: string;\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(max, value));\n\nconst imageElementReady = async (image: HTMLImageElement): Promise<void> => {\n if (image.complete && image.naturalWidth > 0) return;\n await new Promise<void>((resolve, reject) => {\n image.addEventListener(\"load\", () => resolve(), { once: true });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image.\")), { once: true });\n });\n};\n\nconst loadPreviewState = async (source: ImageCropSource): Promise<PreviewState> => {\n const sourceImage =\n source instanceof HTMLImageElement\n ? source\n : Object.assign(new Image(), {\n crossOrigin: source instanceof Blob ? undefined : \"anonymous\",\n src:\n source instanceof HTMLCanvasElement\n ? source.toDataURL(\"image/png\")\n : source instanceof Blob\n ? URL.createObjectURL(source)\n : source,\n });\n\n try {\n await imageElementReady(sourceImage);\n return {\n url: source instanceof HTMLImageElement ? source.currentSrc || source.src : sourceImage.src,\n objectUrl: source instanceof Blob,\n sourceWidth: sourceImage.naturalWidth || sourceImage.width,\n sourceHeight: sourceImage.naturalHeight || sourceImage.height,\n };\n } catch (error) {\n if (source instanceof Blob) URL.revokeObjectURL(sourceImage.src);\n throw error;\n }\n};\n\nexport function ImageCropper(props: ImageCropperProps): JSX.Element {\n const messages = useUiMessages();\n let frame: HTMLDivElement | undefined;\n let activePreview: PreviewState | null = null;\n const aspect = () => props.aspect ?? \"free\";\n const previewShape = () => props.previewShape ?? \"rect\";\n const disabled = () => props.disabled ?? false;\n const [preview, setPreview] = createSignal<PreviewState | null>(null);\n const [crop, setCrop] = createSignal<ImageCropRect | null>(null);\n const [rotation, setRotation] = createSignal<ImageCropRotation>(0);\n const [loading, setLoading] = createSignal(true);\n const [error, setError] = createSignal<string | null>(null);\n const [drag, setDrag] = createSignal<DragState | null>(null);\n\n const previewSize = (): { width: number; height: number } | null => {\n const currentPreview = preview();\n if (!currentPreview) return null;\n const swapsDimensions = rotation() === 90 || rotation() === 270;\n return {\n width: swapsDimensions ? currentPreview.sourceHeight : currentPreview.sourceWidth,\n height: swapsDimensions ? currentPreview.sourceWidth : currentPreview.sourceHeight,\n };\n };\n\n const replacePreview = (next: PreviewState | null) => {\n if (activePreview?.objectUrl) URL.revokeObjectURL(activePreview.url);\n activePreview = next;\n setPreview(next);\n };\n\n onCleanup(() => {\n if (activePreview?.objectUrl) URL.revokeObjectURL(activePreview.url);\n });\n\n createEffect(() => {\n props.source;\n setRotation(0);\n setCrop(null);\n });\n\n createEffect(() => {\n const source = props.source;\n let disposed = false;\n replacePreview(null);\n setLoading(true);\n setError(null);\n\n void (async () => {\n try {\n const nextPreview = await loadPreviewState(source);\n if (disposed) {\n if (nextPreview.objectUrl) URL.revokeObjectURL(nextPreview.url);\n return;\n }\n replacePreview(nextPreview);\n } catch {\n if (disposed) return;\n replacePreview(null);\n setCrop(null);\n setError(messages().failedLoadImage);\n } finally {\n if (!disposed) setLoading(false);\n }\n })();\n\n onCleanup(() => {\n disposed = true;\n });\n });\n\n createEffect(() => {\n const currentSize = previewSize();\n const currentAspect = aspect();\n if (!currentSize) return;\n setCrop((current) => clampImageCropRect(current ?? getInitialImageCropRect(currentSize, currentAspect), currentSize, currentAspect));\n });\n\n createEffect(() => {\n const currentCrop = crop();\n const currentPreview = preview();\n props.onValueChange?.(currentCrop && currentPreview ? { crop: currentCrop, rotation: rotation() } : null);\n });\n\n const readPointerPosition = (event: PointerEvent) => {\n if (!frame) return { x: 0, y: 0 };\n const rect = frame.getBoundingClientRect();\n return {\n x: (event.clientX - rect.left) / Math.max(1, rect.width),\n y: (event.clientY - rect.top) / Math.max(1, rect.height),\n };\n };\n\n const moveCrop = (event: PointerEvent) => {\n const state = drag();\n const currentSize = previewSize();\n if (!state || !currentSize || state.pointerId !== event.pointerId) return;\n event.preventDefault();\n const point = readPointerPosition(event);\n const dx = point.x - state.startX;\n const dy = point.y - state.startY;\n const start = state.startCrop;\n\n if (state.handle === \"move\") {\n setCrop(\n clampImageCropRect(\n {\n ...start,\n x: start.x + dx,\n y: start.y + dy,\n },\n currentSize,\n aspect(),\n ),\n );\n return;\n }\n\n setCrop(resizeImageCropFromCorner(start, currentSize, aspect(), state.handle, dx, dy));\n };\n\n const endDrag = (event: PointerEvent) => {\n const state = drag();\n if (!state || state.pointerId !== event.pointerId) return;\n window.removeEventListener(\"pointermove\", moveCrop);\n window.removeEventListener(\"pointerup\", endDrag);\n window.removeEventListener(\"pointercancel\", endDrag);\n setDrag(null);\n };\n\n const startDrag = (handle: DragHandle, event: PointerEvent) => {\n const currentCrop = crop();\n if (!currentCrop || disabled()) return;\n event.preventDefault();\n event.stopPropagation();\n (event.currentTarget as Element).setPointerCapture?.(event.pointerId);\n const point = readPointerPosition(event);\n setDrag({\n handle,\n pointerId: event.pointerId,\n startX: point.x,\n startY: point.y,\n startCrop: currentCrop,\n });\n window.addEventListener(\"pointermove\", moveCrop);\n window.addEventListener(\"pointerup\", endDrag);\n window.addEventListener(\"pointercancel\", endDrag);\n };\n\n onCleanup(() => {\n if (typeof window === \"undefined\") return;\n window.removeEventListener(\"pointermove\", moveCrop);\n window.removeEventListener(\"pointerup\", endDrag);\n window.removeEventListener(\"pointercancel\", endDrag);\n });\n\n const rotateRight = () => {\n if (disabled()) return;\n setRotation((current) => rotateImageCropRight(current));\n };\n\n const nudgeCrop = (handle: DragHandle, event: KeyboardEvent) => {\n if (disabled() || ![\"ArrowLeft\", \"ArrowRight\", \"ArrowUp\", \"ArrowDown\"].includes(event.key)) return;\n const current = crop();\n const currentSize = previewSize();\n if (!current || !currentSize) return;\n event.preventDefault();\n const step = event.shiftKey ? 0.05 : 0.01;\n const dx = event.key === \"ArrowLeft\" ? -step : event.key === \"ArrowRight\" ? step : 0;\n const dy = event.key === \"ArrowUp\" ? -step : event.key === \"ArrowDown\" ? step : 0;\n setCrop(\n handle === \"move\"\n ? clampImageCropRect({ ...current, x: current.x + dx, y: current.y + dy }, currentSize, aspect())\n : resizeImageCropFromCorner(current, currentSize, aspect(), handle, dx, dy),\n );\n };\n\n const previewFrameStyle = (): JSX.CSSProperties => {\n const currentSize = previewSize();\n if (!currentSize) return {};\n return {\n \"aspect-ratio\": `${currentSize.width} / ${currentSize.height}`,\n \"max-width\": `min(100%, calc(min(58vh, 24rem) * ${currentSize.width} / ${currentSize.height}))`,\n };\n };\n\n const previewImageStyle = (): JSX.CSSProperties => {\n const currentPreview = preview();\n const currentSize = previewSize();\n if (!currentPreview || !currentSize) return {};\n const swapsDimensions = rotation() === 90 || rotation() === 270;\n return {\n left: \"50%\",\n top: \"50%\",\n width: swapsDimensions ? `${(currentPreview.sourceWidth / currentSize.width) * 100}%` : \"100%\",\n height: swapsDimensions ? `${(currentPreview.sourceHeight / currentSize.height) * 100}%` : \"100%\",\n \"max-width\": \"none\",\n \"object-fit\": \"fill\",\n transform: `translate(-50%, -50%) rotate(${rotation()}deg)`,\n };\n };\n\n const cropStyle = (): JSX.CSSProperties => {\n const currentCrop = crop();\n if (!currentCrop) return {};\n return {\n left: `${currentCrop.x * 100}%`,\n top: `${currentCrop.y * 100}%`,\n width: `${currentCrop.width * 100}%`,\n height: `${currentCrop.height * 100}%`,\n \"box-shadow\": \"0 0 0 9999px rgba(0,0,0,.42)\",\n };\n };\n\n const showResizeHandles = () => previewShape() !== \"circle\";\n\n return (\n <div class={`k2b-image-cropper ${props.class ?? \"\"}`}>\n <div class=\"k2b-image-cropper__stage\">\n <Show when={!loading()} fallback={<small>{messages().preparingImage}</small>}>\n <Show when={!error()} fallback={<small class=\"k2b-image-cropper__error\">{error()}</small>}>\n <Show when={preview() && crop()}>\n <div ref={frame} class=\"k2b-image-cropper__frame\" style={previewFrameStyle()}>\n <img src={preview()!.url} alt={messages().cropPreview} draggable={false} style={previewImageStyle()} />\n <div\n class=\"k2b-image-cropper__selection\"\n data-shape={previewShape()}\n style={cropStyle()}\n role=\"group\"\n tabIndex={disabled() ? undefined : 0}\n aria-label={messages().cropArea}\n onPointerDown={(event) => startDrag(\"move\", event)}\n onKeyDown={(event) => nudgeCrop(\"move\", event)}\n >\n <Show when={showResizeHandles()}>\n <For each={[\"nw\", \"ne\", \"sw\", \"se\"] as const}>\n {(handle) => (\n <button\n type=\"button\"\n class=\"k2b-image-cropper__handle\"\n data-handle={handle}\n aria-label={messages().resizeCrop({ handle })}\n disabled={disabled()}\n onPointerDown={(event) => startDrag(handle, event)}\n onKeyDown={(event) => nudgeCrop(handle, event)}\n />\n )}\n </For>\n </Show>\n </div>\n <Tooltip.Trigger\n type=\"button\"\n class=\"k2b-image-cropper__rotate\"\n content={messages().rotateRight}\n aria-label={messages().rotateRight}\n disabled={disabled() || !crop() || Boolean(error())}\n onClick={rotateRight}\n >\n <i class=\"ti ti-rotate-clockwise\" aria-hidden=\"true\" />\n </Tooltip.Trigger>\n </div>\n </Show>\n </Show>\n </Show>\n </div>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["inputs/FileInputs.tsx"],"sourcesContent":["import { createEffect, createMemo, createSignal, For, type JSX, mergeProps, onCleanup, onMount, Show } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { Tooltip } from \"../feedback/Tooltip\";\nimport { createFieldMeta, Field, fieldControlAria } from \"../internal/field\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { fileDropTarget } from \"./FileDropTarget\";\nimport type { FieldProps, ValueFieldProps } from \"./field-contract\";\nimport { commitFieldValue, resolveMaybeAccessor } from \"./field-contract\";\nimport { fileDropEngine, liveDocument } from \"./file-drop\";\nimport {\n clampImageCropRect,\n getInitialImageCropRect,\n type ImageCropAspect,\n type ImageCropRect,\n type ImageCropResizeHandle,\n type ImageCropRotation,\n type ImageCropSource,\n type ImageCropState,\n resizeImageCropFromCorner,\n rotateImageCropRight,\n} from \"./image-crop\";\n\nexport type FileDropzoneProps = FieldProps & {\n accept?: string;\n multiple?: boolean;\n busy?: boolean;\n /** Full icon class list, for example `\"ti ti-photo-plus\"`. Defaults to `\"ti ti-cloud-upload\"`. */\n icon?: string;\n title?: JSX.Element;\n subtitle?: JSX.Element;\n hint?: JSX.Element;\n /** One sentence that says what dropping does, shown while files are over the zone. Defaults to \"Drop to upload\". */\n dropLabel?: string;\n /**\n * Chooses files when the zone is clicked, instead of the device's file dialog, for example to offer other sources as\n * well. Called within the click, so it may still open the device's dialog; resolve `[]` when the user cancels. A\n * rejection shows its message as the field's error.\n */\n choose?: () => Promise<readonly File[]>;\n onDrop: (files: File[]) => void | Promise<void>;\n};\n\nexport function FileDropzone(props: FileDropzoneProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n const disabled = () => Boolean(props.disabled || props.busy);\n const [chooseError, setChooseError] = createSignal<string>();\n const error = () => resolveMaybeAccessor(props.error) ?? chooseError();\n let input: HTMLInputElement | undefined;\n const [button, setButton] = createSignal<HTMLButtonElement>();\n const emit = (files: File[]) => {\n if (disabled() || files.length === 0) return;\n setChooseError();\n void props.onDrop(props.multiple === false ? files.slice(0, 1) : files);\n };\n const choose = (chooseFiles: () => Promise<readonly File[]>) => {\n setChooseError();\n chooseFiles().then(\n (files) => emit([...files]),\n (cause: unknown) => setChooseError(cause instanceof Error && cause.message ? cause.message : messages().failedLoadFiles),\n );\n };\n // Drops take the same path as every other file drop target: files only, the most specific target wins, and files\n // that do not fit `accept` are left out with a message.\n const dropLabel = () => props.dropLabel ?? messages().dropToUpload;\n const dropRef = fileDropTarget({\n get label() {\n return dropLabel();\n },\n get accept() {\n return props.accept;\n },\n get multiple() {\n return props.multiple;\n },\n get disabled() {\n return disabled();\n },\n onDrop: emit,\n });\n const [engine, setEngine] = createSignal<ReturnType<typeof fileDropEngine>>();\n onMount(() => {\n const element = button();\n if (element) setEngine(fileDropEngine(liveDocument(element)));\n });\n const dragState = createMemo(() => {\n const element = button();\n const hover = engine()?.session()?.hover;\n if (!hover || hover.element !== element) return undefined;\n return hover.invalid ? \"invalid\" : \"over\";\n });\n const title = () =>\n props.busy\n ? messages().uploading\n : dragState() === \"invalid\"\n ? messages().fileTypeNotAccepted\n : dragState() === \"over\"\n ? dropLabel()\n : (props.title ?? messages().dropFiles);\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <button\n id={meta.controlId}\n type=\"button\"\n ref={(element) => {\n setButton(element);\n dropRef(element);\n }}\n class=\"k2b-dropzone\"\n data-invalid={error() ? \"true\" : undefined}\n disabled={disabled()}\n {...fieldControlAria(meta, mergeProps(props, { error }))}\n onClick={() => {\n if (props.choose) choose(props.choose);\n else input?.click();\n }}\n >\n <span class=\"k2b-dropzone__icon\" aria-hidden=\"true\">\n <i class={props.busy ? \"ti ti-loader-2 k2b-spin\" : (props.icon ?? \"ti ti-cloud-upload\")} />\n </span>\n <span class=\"k2b-dropzone__copy\">\n <strong>{title()}</strong>\n <Show\n when={dragState() === \"invalid\"}\n fallback={\n <Show when={props.subtitle}>\n <span class=\"k2b-dropzone__subtitle\">{props.subtitle}</span>\n </Show>\n }\n >\n <span class=\"k2b-dropzone__subtitle\">{messages().chooseMatchingFile}</span>\n </Show>\n <Show when={props.hint}>\n <span class=\"k2b-dropzone__hint\">{props.hint}</span>\n </Show>\n </span>\n </button>\n {/* With `choose`, the zone is the only control: a native input would take a dialog's first focus and open the\n device's dialog past the chooser. */}\n <Show when={!props.choose}>\n <input\n ref={input}\n class=\"k2b-sr-only\"\n type=\"file\"\n aria-label={\n props[\"aria-label\"] ??\n (typeof props.label === \"string\" ? props.label : props.multiple === false ? messages().chooseFile : messages().chooseFiles)\n }\n accept={props.accept}\n multiple={props.multiple ?? true}\n disabled={disabled()}\n tabIndex={-1}\n onChange={(event) => {\n const files = Array.from(event.currentTarget.files ?? []);\n // Reset before emitting so re-picking the same file still fires change,\n // even when onDrop throws.\n event.currentTarget.value = \"\";\n emit(files);\n }}\n />\n </Show>\n </Field>\n );\n}\n\nexport type ImageInputProps = ValueFieldProps<string | null> & {\n round?: boolean;\n variant?: \"default\" | \"small\";\n transform?: (file: File) => Promise<string>;\n accept?: string;\n fallbackMarker?: string;\n};\n\nconst DEFAULT_IMAGE_ACCEPT = \"image/jpeg,image/png,image/gif,image/webp,image/svg+xml,.jpg,.jpeg,.png,.gif,.webp,.svg\";\n\nconst defaultImageTransform = async (file: File): Promise<string> => {\n const { img } = await import(\"@k2b/stdlib/browser\");\n return img.presets.avatar(file);\n};\n\nexport function ImageInput(props: ImageInputProps): JSX.Element {\n const messages = useUiMessages();\n const meta = createFieldMeta(props.id);\n const [busy, setBusy] = createSignal(false);\n const [localError, setLocalError] = createSignal<string>();\n let input: HTMLInputElement | undefined;\n const disabled = () => Boolean(props.disabled || busy() || !props.onValueChange);\n const error = () => resolveMaybeAccessor(props.error) ?? localError();\n const value = () => {\n const current = resolveMaybeAccessor(props.value);\n return current && !current.includes(props.fallbackMarker ?? \"?fallback\") ? current : null;\n };\n const compact = () => props.variant === \"small\";\n const changeLabel = () => (value() ? messages().changeImage : messages().addImage);\n const changeIcon = () => (value() ? \"ti ti-pencil\" : \"ti ti-photo-plus\");\n const select = async (file: File | undefined) => {\n if (!file || disabled()) return;\n setBusy(true);\n setLocalError();\n try {\n const transformed = await (props.transform ?? defaultImageTransform)(file);\n commitFieldValue(props, transformed);\n } catch (error) {\n setLocalError(error instanceof Error ? error.message : messages().imageProcessingFailed);\n } finally {\n setBusy(false);\n if (input) input.value = \"\";\n }\n };\n\n return (\n <Field\n class={props.class}\n label={props.label}\n description={props.description}\n error={error()}\n meta={meta}\n required={props.required}\n disabled={disabled()}\n >\n <div\n class=\"k2b-image-input\"\n data-round={props.round ? \"true\" : undefined}\n data-variant={props.variant ?? \"default\"}\n role=\"group\"\n aria-labelledby={props.label ? meta.labelId : undefined}\n aria-label={!props.label ? props[\"aria-label\"] : undefined}\n aria-describedby={fieldControlAria(meta, { ...props, error })[\"aria-describedby\"]}\n >\n <div class=\"k2b-image-input__preview\">\n <Show when={value()} fallback={<i class=\"ti ti-photo-off\" aria-hidden=\"true\" />}>\n {(source) => <img src={source()} alt={typeof props.label === \"string\" ? props.label : messages().selectedImage} />}\n </Show>\n </div>\n <div class=\"k2b-image-input__actions\">\n <Show\n when={compact()}\n fallback={\n <Button\n variant=\"secondary\"\n loading={busy()}\n loadingLabel={messages().processingImage}\n disabled={disabled()}\n onClick={() => input?.click()}\n >\n <i class={changeIcon()} aria-hidden=\"true\" />\n {value() ? messages().change : messages().add}\n </Button>\n }\n >\n <IconButton\n label={changeLabel()}\n loading={busy()}\n loadingLabel={messages().processingImage}\n disabled={disabled()}\n onClick={() => input?.click()}\n >\n <i class={changeIcon()} aria-hidden=\"true\" />\n </IconButton>\n </Show>\n <Show when={value()}>\n <Show\n when={compact()}\n fallback={\n <Button variant=\"ghost\" disabled={disabled()} onClick={() => commitFieldValue(props, null)}>\n <i class=\"ti ti-trash\" aria-hidden=\"true\" /> Remove\n </Button>\n }\n >\n <IconButton label={messages().removeImage} disabled={disabled()} onClick={() => commitFieldValue(props, null)}>\n <i class=\"ti ti-trash\" aria-hidden=\"true\" />\n </IconButton>\n </Show>\n </Show>\n </div>\n <input\n ref={input}\n id={meta.controlId}\n class=\"k2b-sr-only\"\n type=\"file\"\n accept={props.accept ?? DEFAULT_IMAGE_ACCEPT}\n disabled={disabled()}\n required={props.required && !value()}\n {...fieldControlAria(meta, { ...props, error })}\n onChange={(event) => void select(event.currentTarget.files?.[0])}\n />\n </div>\n </Field>\n );\n}\n\ntype PreviewState = {\n url: string;\n objectUrl: boolean;\n sourceWidth: number;\n sourceHeight: number;\n};\n\ntype DragHandle = \"move\" | ImageCropResizeHandle;\ntype DragState = {\n handle: DragHandle;\n pointerId: number;\n startX: number;\n startY: number;\n startCrop: ImageCropRect;\n};\n\nexport type ImageCropperProps = {\n source: ImageCropSource;\n aspect?: ImageCropAspect;\n previewShape?: \"rect\" | \"circle\";\n disabled?: boolean;\n onValueChange?: (state: ImageCropState | null) => void;\n class?: string;\n};\n\nconst clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(max, value));\n\nconst imageElementReady = async (image: HTMLImageElement): Promise<void> => {\n if (image.complete && image.naturalWidth > 0) return;\n await new Promise<void>((resolve, reject) => {\n image.addEventListener(\"load\", () => resolve(), { once: true });\n image.addEventListener(\"error\", () => reject(new Error(\"Failed to load image.\")), { once: true });\n });\n};\n\nconst loadPreviewState = async (source: ImageCropSource): Promise<PreviewState> => {\n const sourceImage =\n source instanceof HTMLImageElement\n ? source\n : Object.assign(new Image(), {\n crossOrigin: source instanceof Blob ? undefined : \"anonymous\",\n src:\n source instanceof HTMLCanvasElement\n ? source.toDataURL(\"image/png\")\n : source instanceof Blob\n ? URL.createObjectURL(source)\n : source,\n });\n\n try {\n await imageElementReady(sourceImage);\n return {\n url: source instanceof HTMLImageElement ? source.currentSrc || source.src : sourceImage.src,\n objectUrl: source instanceof Blob,\n sourceWidth: sourceImage.naturalWidth || sourceImage.width,\n sourceHeight: sourceImage.naturalHeight || sourceImage.height,\n };\n } catch (error) {\n if (source instanceof Blob) URL.revokeObjectURL(sourceImage.src);\n throw error;\n }\n};\n\nexport function ImageCropper(props: ImageCropperProps): JSX.Element {\n const messages = useUiMessages();\n let frame: HTMLDivElement | undefined;\n let activePreview: PreviewState | null = null;\n const aspect = () => props.aspect ?? \"free\";\n const previewShape = () => props.previewShape ?? \"rect\";\n const disabled = () => props.disabled ?? false;\n const [preview, setPreview] = createSignal<PreviewState | null>(null);\n const [crop, setCrop] = createSignal<ImageCropRect | null>(null);\n const [rotation, setRotation] = createSignal<ImageCropRotation>(0);\n const [loading, setLoading] = createSignal(true);\n const [error, setError] = createSignal<string | null>(null);\n const [drag, setDrag] = createSignal<DragState | null>(null);\n\n const previewSize = (): { width: number; height: number } | null => {\n const currentPreview = preview();\n if (!currentPreview) return null;\n const swapsDimensions = rotation() === 90 || rotation() === 270;\n return {\n width: swapsDimensions ? currentPreview.sourceHeight : currentPreview.sourceWidth,\n height: swapsDimensions ? currentPreview.sourceWidth : currentPreview.sourceHeight,\n };\n };\n\n const replacePreview = (next: PreviewState | null) => {\n if (activePreview?.objectUrl) URL.revokeObjectURL(activePreview.url);\n activePreview = next;\n setPreview(next);\n };\n\n onCleanup(() => {\n if (activePreview?.objectUrl) URL.revokeObjectURL(activePreview.url);\n });\n\n createEffect(() => {\n props.source;\n setRotation(0);\n setCrop(null);\n });\n\n createEffect(() => {\n const source = props.source;\n let disposed = false;\n replacePreview(null);\n setLoading(true);\n setError(null);\n\n void (async () => {\n try {\n const nextPreview = await loadPreviewState(source);\n if (disposed) {\n if (nextPreview.objectUrl) URL.revokeObjectURL(nextPreview.url);\n return;\n }\n replacePreview(nextPreview);\n } catch {\n if (disposed) return;\n replacePreview(null);\n setCrop(null);\n setError(messages().failedLoadImage);\n } finally {\n if (!disposed) setLoading(false);\n }\n })();\n\n onCleanup(() => {\n disposed = true;\n });\n });\n\n createEffect(() => {\n const currentSize = previewSize();\n const currentAspect = aspect();\n if (!currentSize) return;\n setCrop((current) => clampImageCropRect(current ?? getInitialImageCropRect(currentSize, currentAspect), currentSize, currentAspect));\n });\n\n createEffect(() => {\n const currentCrop = crop();\n const currentPreview = preview();\n props.onValueChange?.(currentCrop && currentPreview ? { crop: currentCrop, rotation: rotation() } : null);\n });\n\n const readPointerPosition = (event: PointerEvent) => {\n if (!frame) return { x: 0, y: 0 };\n const rect = frame.getBoundingClientRect();\n return {\n x: (event.clientX - rect.left) / Math.max(1, rect.width),\n y: (event.clientY - rect.top) / Math.max(1, rect.height),\n };\n };\n\n const moveCrop = (event: PointerEvent) => {\n const state = drag();\n const currentSize = previewSize();\n if (!state || !currentSize || state.pointerId !== event.pointerId) return;\n event.preventDefault();\n const point = readPointerPosition(event);\n const dx = point.x - state.startX;\n const dy = point.y - state.startY;\n const start = state.startCrop;\n\n if (state.handle === \"move\") {\n setCrop(\n clampImageCropRect(\n {\n ...start,\n x: start.x + dx,\n y: start.y + dy,\n },\n currentSize,\n aspect(),\n ),\n );\n return;\n }\n\n setCrop(resizeImageCropFromCorner(start, currentSize, aspect(), state.handle, dx, dy));\n };\n\n const endDrag = (event: PointerEvent) => {\n const state = drag();\n if (!state || state.pointerId !== event.pointerId) return;\n window.removeEventListener(\"pointermove\", moveCrop);\n window.removeEventListener(\"pointerup\", endDrag);\n window.removeEventListener(\"pointercancel\", endDrag);\n setDrag(null);\n };\n\n const startDrag = (handle: DragHandle, event: PointerEvent) => {\n const currentCrop = crop();\n if (!currentCrop || disabled()) return;\n event.preventDefault();\n event.stopPropagation();\n (event.currentTarget as Element).setPointerCapture?.(event.pointerId);\n const point = readPointerPosition(event);\n setDrag({\n handle,\n pointerId: event.pointerId,\n startX: point.x,\n startY: point.y,\n startCrop: currentCrop,\n });\n window.addEventListener(\"pointermove\", moveCrop);\n window.addEventListener(\"pointerup\", endDrag);\n window.addEventListener(\"pointercancel\", endDrag);\n };\n\n onCleanup(() => {\n if (typeof window === \"undefined\") return;\n window.removeEventListener(\"pointermove\", moveCrop);\n window.removeEventListener(\"pointerup\", endDrag);\n window.removeEventListener(\"pointercancel\", endDrag);\n });\n\n const rotateRight = () => {\n if (disabled()) return;\n setRotation((current) => rotateImageCropRight(current));\n };\n\n const nudgeCrop = (handle: DragHandle, event: KeyboardEvent) => {\n if (disabled() || ![\"ArrowLeft\", \"ArrowRight\", \"ArrowUp\", \"ArrowDown\"].includes(event.key)) return;\n const current = crop();\n const currentSize = previewSize();\n if (!current || !currentSize) return;\n event.preventDefault();\n const step = event.shiftKey ? 0.05 : 0.01;\n const dx = event.key === \"ArrowLeft\" ? -step : event.key === \"ArrowRight\" ? step : 0;\n const dy = event.key === \"ArrowUp\" ? -step : event.key === \"ArrowDown\" ? step : 0;\n setCrop(\n handle === \"move\"\n ? clampImageCropRect({ ...current, x: current.x + dx, y: current.y + dy }, currentSize, aspect())\n : resizeImageCropFromCorner(current, currentSize, aspect(), handle, dx, dy),\n );\n };\n\n const previewFrameStyle = (): JSX.CSSProperties => {\n const currentSize = previewSize();\n if (!currentSize) return {};\n return {\n \"aspect-ratio\": `${currentSize.width} / ${currentSize.height}`,\n \"max-width\": `min(100%, calc(min(58vh, 24rem) * ${currentSize.width} / ${currentSize.height}))`,\n };\n };\n\n const previewImageStyle = (): JSX.CSSProperties => {\n const currentPreview = preview();\n const currentSize = previewSize();\n if (!currentPreview || !currentSize) return {};\n const swapsDimensions = rotation() === 90 || rotation() === 270;\n return {\n left: \"50%\",\n top: \"50%\",\n width: swapsDimensions ? `${(currentPreview.sourceWidth / currentSize.width) * 100}%` : \"100%\",\n height: swapsDimensions ? `${(currentPreview.sourceHeight / currentSize.height) * 100}%` : \"100%\",\n \"max-width\": \"none\",\n \"object-fit\": \"fill\",\n transform: `translate(-50%, -50%) rotate(${rotation()}deg)`,\n };\n };\n\n const cropStyle = (): JSX.CSSProperties => {\n const currentCrop = crop();\n if (!currentCrop) return {};\n return {\n left: `${currentCrop.x * 100}%`,\n top: `${currentCrop.y * 100}%`,\n width: `${currentCrop.width * 100}%`,\n height: `${currentCrop.height * 100}%`,\n \"box-shadow\": \"0 0 0 9999px rgba(0,0,0,.42)\",\n };\n };\n\n const showResizeHandles = () => previewShape() !== \"circle\";\n\n return (\n <div class={`k2b-image-cropper ${props.class ?? \"\"}`}>\n <div class=\"k2b-image-cropper__stage\">\n <Show when={!loading()} fallback={<small>{messages().preparingImage}</small>}>\n <Show when={!error()} fallback={<small class=\"k2b-image-cropper__error\">{error()}</small>}>\n <Show when={preview() && crop()}>\n <div ref={frame} class=\"k2b-image-cropper__frame\" style={previewFrameStyle()}>\n <img src={preview()!.url} alt={messages().cropPreview} draggable={false} style={previewImageStyle()} />\n <div\n class=\"k2b-image-cropper__selection\"\n data-shape={previewShape()}\n style={cropStyle()}\n role=\"group\"\n tabIndex={disabled() ? undefined : 0}\n aria-label={messages().cropArea}\n onPointerDown={(event) => startDrag(\"move\", event)}\n onKeyDown={(event) => nudgeCrop(\"move\", event)}\n >\n <Show when={showResizeHandles()}>\n <For each={[\"nw\", \"ne\", \"sw\", \"se\"] as const}>\n {(handle) => (\n <button\n type=\"button\"\n class=\"k2b-image-cropper__handle\"\n data-handle={handle}\n aria-label={messages().resizeCrop({ handle })}\n disabled={disabled()}\n onPointerDown={(event) => startDrag(handle, event)}\n onKeyDown={(event) => nudgeCrop(handle, event)}\n />\n )}\n </For>\n </Show>\n </div>\n <Tooltip.Trigger\n type=\"button\"\n class=\"k2b-image-cropper__rotate\"\n content={messages().rotateRight}\n aria-label={messages().rotateRight}\n disabled={disabled() || !crop() || Boolean(error())}\n onClick={rotateRight}\n >\n <i class=\"ti ti-rotate-clockwise\" aria-hidden=\"true\" />\n </Tooltip.Trigger>\n </div>\n </Show>\n </Show>\n </Show>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAY,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,QAAQ,UAAU;AACtH,SAAS,MAAM,EAAE,UAAU,QAAQ,mBAAmB;AACtD,SAAS,OAAO,QAAQ,qBAAqB;AAC7C,SAAS,eAAe,EAAE,KAAK,EAAE,gBAAgB,QAAQ,mBAAmB;AAC5E,SAAS,aAAa,QAAQ,kBAAkB;AAChD,SAAS,cAAc,QAAQ,kBAAkB;AAEjD,SAAS,gBAAgB,EAAE,oBAAoB,QAAQ,kBAAkB;AACzE,SAAS,cAAc,EAAE,YAAY,QAAQ,aAAa;AAC1D,SACE,kBAAkB,EAClB,uBAAuB,EAOvB,yBAAyB,EACzB,oBAAoB,QACf,cAAc;AAsBrB,OAAO,SAAS,YAAY,CAAC,KAAwB,EAAe;EAClE,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;EACtC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;EAC5D,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,YAAY,CAAS,CAAC;EAC5D,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,CAAC;EACtE,IAAI,KAAmC;EACvC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,YAAY,CAAoB,CAAC;EAC7D,MAAM,IAAI,GAAI,KAAa,IAAK;IAC9B,IAAI,QAAQ,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;IACtC,cAAc,CAAC,CAAC;IAChB,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;EACzE,CAAC;EACD,MAAM,MAAM,GAAI,WAA2C,IAAK;IAC9D,cAAc,CAAC,CAAC;IAChB,WAAW,CAAC,CAAC,CAAC,IAAI,CACf,KAAK,IAAK,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAC1B,KAAc,IAAK,cAAc,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CACzH,CAAC;EACH,CAAC;EACD;EACA;EACA,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,YAAY;EAClE,MAAM,OAAO,GAAG,cAAc,CAAC;IAC7B,IAAI,KAAK,GAAG;MACV,OAAO,SAAS,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,MAAM,GAAG;MACX,OAAO,KAAK,CAAC,MAAM;IACrB,CAAC;IACD,IAAI,QAAQ,GAAG;MACb,OAAO,KAAK,CAAC,QAAQ;IACvB,CAAC;IACD,IAAI,QAAQ,GAAG;MACb,OAAO,QAAQ,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,EAAE;EACV,CAAC,CAAC;EACF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,YAAY,CAAoC,CAAC;EAC7E,OAAO,CAAC,MAAM;IACZ,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC;IACxB,IAAI,OAAO,EAAE,SAAS,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;EAC/D,CAAC,CAAC;EACF,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK;IACxC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE,OAAO,SAAS;IACzD,OAAO,KAAK,CAAC,OAAO,GAAG,SAAS,GAAG,MAAM;EAC3C,CAAC,CAAC;EACF,MAAM,KAAK,GAAG,MACZ,KAAK,CAAC,IAAI,GACN,QAAQ,CAAC,CAAC,CAAC,SAAS,GACpB,SAAS,CAAC,CAAC,KAAK,SAAS,GACvB,QAAQ,CAAC,CAAC,CAAC,mBAAmB,GAC9B,SAAS,CAAC,CAAC,KAAK,MAAM,GACpB,SAAS,CAAC,CAAC,GACV,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAU;EAE/C,yBACG,KAAK;IAAA;MAAA,OACG,KAAK,CAAC,KAAK;IAAA;IAAA,IAClB,KAAK;MAAA,OAAE,KAAK,CAAC,KAAK;IAAA;IAAA,IAClB,WAAW;MAAA,OAAE,KAAK,CAAC,WAAW;IAAA;IAAA,IAC9B,KAAK;MAAA,OAAE,KAAK,CAAC,CAAC;IAAA;IACd,IAAI,EAAE,IAAI;IAAA,IACV,QAAQ;MAAA,OAAE,KAAK,CAAC,QAAQ;IAAA;IAAA,IACxB,QAAQ;MAAA,OAAE,QAAQ,CAAC,CAAC;IAAA;IAAA;MAAA;QAAA,IAGlB,EAAE;UAAA,OAAE,IAAI,CAAC,SAAS;QAAA;QAClB,IAAI,EAAC,QAAQ;QAAA,SAKP,cAAc;QAAA;UAAA,OACN,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,SAAS;QAAA;QAAA,IAC1C,QAAQ;UAAA,OAAE,QAAQ,CAAC,CAAC;QAAA;MAAA,SAChB,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE;QAAE;MAAM,CAAC,CAAC,CAAC,0CAO5C,KAAK,CAAC,IAAI,GAAG,yBAAyB,YAAI,KAAK,CAAC,IAAI,IAAI,oBAAoB,OAAC,mCAG9E,KAAK,CAAC,CAAC,8BACf,IAAI;QAAA,IACH,IAAI;UAAA,OAAE,SAAS,CAAC,CAAC,KAAK,SAAS;QAAA;QAAA,IAC/B,QAAQ;UAAA,yBACL,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,KAAK,CAAC,QAAQ;YAAA;YAAA;cAAA,+BACc,KAAK,CAAC,QAAQ;YAAA;UAAA;QAAA;QAAA;UAAA,+BAIlB,QAAQ,CAAC,CAAC,CAAC,kBAAkB;QAAA;MAAA,gCAEpE,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,IAAI;QAAA;QAAA;UAAA,+BACc,KAAK,CAAC,IAAI;QAAA;MAAA,iCAMjD,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,CAAC,KAAK,CAAC,MAAM;QAAA;QAAA;UAAA,4DAMnB,KAAK,CAAC,YAAY,CAAC,KAClB,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,oDAErH,KAAK,CAAC,MAAM,4CACV,KAAK,CAAC,QAAQ,IAAI,IAAI,oCACtB,QAAQ,CAAC,CAAC;QAAA;MAAA;IAAA;EAAA;AAa9B;AAUA,MAAM,oBAAoB,GAAG,yFAAyF;AAEtH,MAAM,qBAAqB,GAAG,MAAO,IAAU,IAAsB;EACnE,MAAM;IAAE;EAAI,CAAC,GAAG,MAAM,OAAO,qBAAqB,CAAC;EACnD,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,OAAO,SAAS,UAAU,CAAC,KAAsB,EAAe;EAC9D,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;EACtC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC;EAC3C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,YAAY,CAAS,CAAC;EAC1D,IAAI,KAAmC;EACvC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;EAChF,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC;EACrE,MAAM,KAAK,GAAG,MAAM;IAClB,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC;IACjD,OAAO,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,IAAI,WAAW,CAAC,GAAG,OAAO,GAAG,IAAI;EAC3F,CAAC;EACD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,KAAK,OAAO;EAC/C,MAAM,WAAW,GAAG,MAAO,KAAK,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAS;EAClF,MAAM,UAAU,GAAG,MAAO,KAAK,CAAC,CAAC,GAAG,cAAc,GAAG,kBAAmB;EACxE,MAAM,MAAM,GAAG,MAAO,IAAsB,IAAK;IAC/C,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,EAAE;IACzB,OAAO,CAAC,IAAI,CAAC;IACb,aAAa,CAAC,CAAC;IACf,IAAI;MACF,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,qBAAqB,EAAE,IAAI,CAAC;MAC1E,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC;IACtC,CAAC,CAAC,OAAO,KAAK,EAAE;MACd,aAAa,CAAC,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC1F,CAAC,SAAS;MACR,OAAO,CAAC,KAAK,CAAC;MACd,IAAI,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,EAAE;IAC7B;EACF,CAAC;EAED,yBACG,KAAK;IAAA;MAAA,OACG,KAAK,CAAC,KAAK;IAAA;IAAA,IAClB,KAAK;MAAA,OAAE,KAAK,CAAC,KAAK;IAAA;IAAA,IAClB,WAAW;MAAA,OAAE,KAAK,CAAC,WAAW;IAAA;IAAA,IAC9B,KAAK;MAAA,OAAE,KAAK,CAAC,CAAC;IAAA;IACd,IAAI,EAAE,IAAI;IAAA,IACV,QAAQ;MAAA,OAAE,KAAK,CAAC,QAAQ;IAAA;IAAA,IACxB,QAAQ;MAAA,OAAE,QAAQ,CAAC,CAAC;IAAA;IAAA;MAAA,mDAIN,KAAK,CAAC,KAAK,GAAG,MAAM,YAAG,SAAS,0DAC9B,KAAK,CAAC,OAAO,IAAI,SAAS,mDAEvB,KAAK,CAAC,KAAK,YAAG,IAAI,CAAC,OAAO,mBAAG,SAAS,+CAC3C,CAAC,KAAK,CAAC,KAAK,YAAG,KAAK,CAAC,YAAY,CAAC,mBAAG,SAAS,8DACxC,gBAAgB,CAAC,IAAI,EAAE;QAAE,GAAG,KAAK;QAAE;MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,4CAG9E,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,CAAC;QAAA;QAAA,IAAE,QAAQ;UAAA;QAAA;QAAA,UACzB,MAAM,kDAAe,MAAM,CAAC,CAAC,wCAAO,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,YAAG,KAAK,CAAC,KAAK,mBAAG,QAAQ,CAAC,CAAC,CAAC,aAAa;MAAI,gCAInH,IAAI;QAAA,IACH,IAAI;UAAA,OAAE,OAAO,CAAC,CAAC;QAAA;QAAA,IACf,QAAQ;UAAA,yBACL,MAAM;YACL,OAAO;YAAA,IACP,OAAO;cAAA,OAAE,IAAI,CAAC,CAAC;YAAA;YAAA,IACf,YAAY;cAAA,OAAE,QAAQ,CAAC,CAAC,CAAC,eAAe;YAAA;YAAA,IACxC,QAAQ;cAAA,OAAE,QAAQ,CAAC,CAAC;YAAA;YACpB,OAAO,EAAE,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;YAAA;cAAA,wDAEnB,UAAU,CAAC,CAAC,kBACrB,KAAK,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG;YAAA;UAAA;QAAA;QAAA;UAAA,yBAIhD,UAAU;YAAA,IACT,KAAK;cAAA,OAAE,WAAW,CAAC,CAAC;YAAA;YAAA,IACpB,OAAO;cAAA,OAAE,IAAI,CAAC,CAAC;YAAA;YAAA,IACf,YAAY;cAAA,OAAE,QAAQ,CAAC,CAAC,CAAC,eAAe;YAAA;YAAA,IACxC,QAAQ;cAAA,OAAE,QAAQ,CAAC,CAAC;YAAA;YACpB,OAAO,EAAE,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC;YAAA;cAAA,uDAEnB,UAAU,CAAC,CAAC;YAAA;UAAA;QAAA;MAAA,gCAGzB,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,CAAC;QAAA;QAAA;UAAA,yBAChB,IAAI;YAAA,IACH,IAAI;cAAA,OAAE,OAAO,CAAC,CAAC;YAAA;YAAA,IACf,QAAQ;cAAA,yBACL,MAAM;gBAAC,OAAO;gBAAA,IAAS,QAAQ;kBAAA,OAAE,QAAQ,CAAC,CAAC;gBAAA;gBAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC;gBAAA;kBAAA;gBAAA;cAAA;YAAA;YAAA;cAAA,yBAK3F,UAAU;gBAAA,IAAC,KAAK;kBAAA,OAAE,QAAQ,CAAC,CAAC,CAAC,WAAW;gBAAA;gBAAA,IAAE,QAAQ;kBAAA,OAAE,QAAQ,CAAC,CAAC;gBAAA;gBAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC;gBAAA;kBAAA;gBAAA;cAAA;YAAA;UAAA;QAAA;MAAA;QAAA,IAQjH,EAAE;UAAA,OAAE,IAAI,CAAC,SAAS;QAAA;QAAA,SACZ,aAAa;QACnB,IAAI,EAAC,MAAM;QAAA,IACX,MAAM;UAAA,OAAE,KAAK,CAAC,MAAM,IAAI,oBAAoB;QAAA;QAAA,IAC5C,QAAQ;UAAA,OAAE,QAAQ,CAAC,CAAC;QAAA;QAAA,IACpB,QAAQ;UAAA,OAAE,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC;QAAA;MAAA,SAChC,gBAAgB,CAAC,IAAI,EAAE;QAAE,GAAG,KAAK;QAAE;MAAM,CAAC,CAAC;IAAA;EAAA;AAMzD;AA2BA,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAE9F,MAAM,iBAAiB,GAAG,MAAO,KAAuB,IAAoB;EAC1E,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,EAAE;EAC9C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAK;IAC3C,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,EAAE;MAAE,IAAI,EAAE;IAAK,CAAC,CAAC;IAC/D,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAAE;MAAE,IAAI,EAAE;IAAK,CAAC,CAAC;EACnG,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,gBAAgB,GAAG,MAAO,MAAuB,IAA4B;EACjF,MAAM,WAAW,GACf,MAAM,YAAY,gBAAgB,GAC9B,MAAM,GACN,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE;IACzB,WAAW,EAAE,MAAM,YAAY,IAAI,GAAG,SAAS,GAAG,WAAW;IAC7D,GAAG,EACD,MAAM,YAAY,iBAAiB,GAC/B,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,GAC7B,MAAM,YAAY,IAAI,GACpB,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,GAC3B;EACV,CAAC,CAAC;EAER,IAAI;IACF,MAAM,iBAAiB,CAAC,WAAW,CAAC;IACpC,OAAO;MACL,GAAG,EAAE,MAAM,YAAY,gBAAgB,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,GAAG,WAAW,CAAC,GAAG;MAC3F,SAAS,EAAE,MAAM,YAAY,IAAI;MACjC,WAAW,EAAE,WAAW,CAAC,YAAY,IAAI,WAAW,CAAC,KAAK;MAC1D,YAAY,EAAE,WAAW,CAAC,aAAa,IAAI,WAAW,CAAC;IACzD,CAAC;EACH,CAAC,CAAC,OAAO,KAAK,EAAE;IACd,IAAI,MAAM,YAAY,IAAI,EAAE,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC,GAAG,CAAC;IAChE,MAAM,KAAK;EACb;AACF,CAAC;AAED,OAAO,SAAS,YAAY,CAAC,KAAwB,EAAe;EAClE,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,IAAI,KAAiC;EACrC,IAAI,aAAkC,GAAG,IAAI;EAC7C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,IAAI,MAAM;EAC3C,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,YAAY,IAAI,MAAM;EACvD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,IAAI,KAAK;EAC9C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAsB,IAAI,CAAC;EACrE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,YAAY,CAAuB,IAAI,CAAC;EAChE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,YAAY,CAAoB,CAAC,CAAC;EAClE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC;EAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAgB,IAAI,CAAC;EAC3D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,YAAY,CAAmB,IAAI,CAAC;EAE5D,MAAM,WAAW,GAAG,MAAgD;IAClE,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,cAAc,EAAE,OAAO,IAAI;IAChC,MAAM,eAAe,GAAG,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,CAAC,KAAK,GAAG;IAC/D,OAAO;MACL,KAAK,EAAE,eAAe,GAAG,cAAc,CAAC,YAAY,GAAG,cAAc,CAAC,WAAW;MACjF,MAAM,EAAE,eAAe,GAAG,cAAc,CAAC,WAAW,GAAG,cAAc,CAAC;IACxE,CAAC;EACH,CAAC;EAED,MAAM,cAAc,GAAI,IAAyB,IAAK;IACpD,IAAI,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,eAAe,CAAC,aAAa,CAAC,GAAG,CAAC;IACpE,aAAa,GAAG,IAAI;IACpB,UAAU,CAAC,IAAI,CAAC;EAClB,CAAC;EAED,SAAS,CAAC,MAAM;IACd,IAAI,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,eAAe,CAAC,aAAa,CAAC,GAAG,CAAC;EACtE,CAAC,CAAC;EAEF,YAAY,CAAC,MAAM;IACjB,KAAK,CAAC,MAAM;IACZ,WAAW,CAAC,CAAC,CAAC;IACd,OAAO,CAAC,IAAI,CAAC;EACf,CAAC,CAAC;EAEF,YAAY,CAAC,MAAM;IACjB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;IAC3B,IAAI,QAAQ,GAAG,KAAK;IACpB,cAAc,CAAC,IAAI,CAAC;IACpB,UAAU,CAAC,IAAI,CAAC;IAChB,QAAQ,CAAC,IAAI,CAAC;IAEd,KAAK,CAAC,YAAY;MAChB,IAAI;QACF,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC;QAClD,IAAI,QAAQ,EAAE;UACZ,IAAI,WAAW,CAAC,SAAS,EAAE,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC,GAAG,CAAC;UAC/D;QACF;QACA,cAAc,CAAC,WAAW,CAAC;MAC7B,CAAC,CAAC,MAAM;QACN,IAAI,QAAQ,EAAE;QACd,cAAc,CAAC,IAAI,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC;QACb,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC;MACtC,CAAC,SAAS;QACR,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC;MAClC;IACF,CAAC,EAAE,CAAC;IAEJ,SAAS,CAAC,MAAM;MACd,QAAQ,GAAG,IAAI;IACjB,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF,YAAY,CAAC,MAAM;IACjB,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC;IACjC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC;IAC9B,IAAI,CAAC,WAAW,EAAE;IAClB,OAAO,CAAE,OAAO,IAAK,kBAAkB,CAAC,OAAO,IAAI,uBAAuB,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;EACtI,CAAC,CAAC;EAEF,YAAY,CAAC,MAAM;IACjB,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1B,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,aAAa,GAAG,WAAW,IAAI,cAAc,GAAG;MAAE,IAAI,EAAE,WAAW;MAAE,QAAQ,EAAE,QAAQ,CAAC;IAAE,CAAC,GAAG,IAAI,CAAC;EAC3G,CAAC,CAAC;EAEF,MAAM,mBAAmB,GAAI,KAAmB,IAAK;IACnD,IAAI,CAAC,KAAK,EAAE,OAAO;MAAE,CAAC,EAAE,CAAC;MAAE,CAAC,EAAE;IAAE,CAAC;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC1C,OAAO;MACL,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;MACxD,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM;IACzD,CAAC;EACH,CAAC;EAED,MAAM,QAAQ,GAAI,KAAmB,IAAK;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC;IACpB,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,EAAE;IACnE,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC;IACxC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM;IACjC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM;IACjC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS;IAE7B,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE;MAC3B,OAAO,CACL,kBAAkB,CAChB;QACE,GAAG,KAAK;QACR,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE;QACf,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG;MACf,CAAC,EACD,WAAW,EACX,MAAM,CAAC,CACT,CACF,CAAC;MACD;IACF;IAEA,OAAO,CAAC,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;EACxF,CAAC;EAED,MAAM,OAAO,GAAI,KAAmB,IAAK;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC;IACpB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,EAAE;IACnD,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,QAAQ,CAAC;IACnD,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC;IAChD,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,OAAO,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC;EACf,CAAC;EAED,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAE,KAAmB,KAAK;IAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,WAAW,IAAI,QAAQ,CAAC,CAAC,EAAE;IAChC,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,KAAK,CAAC,eAAe,CAAC,CAAC;IACtB,KAAK,CAAC,aAAa,CAAa,iBAAiB,GAAG,KAAK,CAAC,SAAS,CAAC;IACrE,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC;IACxC,OAAO,CAAC;MACN,MAAM;MACN,SAAS,EAAE,KAAK,CAAC,SAAS;MAC1B,MAAM,EAAE,KAAK,CAAC,CAAC;MACf,MAAM,EAAE,KAAK,CAAC,CAAC;MACf,SAAS,EAAE;IACb,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,QAAQ,CAAC;IAChD,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC;IAC7C,MAAM,CAAC,gBAAgB,CAAC,eAAe,EAAE,OAAO,CAAC;EACnD,CAAC;EAED,SAAS,CAAC,MAAM;IACd,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;IACnC,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,QAAQ,CAAC;IACnD,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC;IAChD,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,OAAO,CAAC;EACtD,CAAC,CAAC;EAEF,MAAM,WAAW,GAAG,MAAM;IACxB,IAAI,QAAQ,CAAC,CAAC,EAAE;IAChB,WAAW,CAAE,OAAO,IAAK,oBAAoB,CAAC,OAAO,CAAC,CAAC;EACzD,CAAC;EAED,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAE,KAAoB,KAAK;IAC9D,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IAC5F,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC;IACtB,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE;IAC9B,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI;IACzC,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,KAAK,WAAW,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,YAAY,GAAG,IAAI,GAAG,CAAC;IACpF,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,KAAK,SAAS,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,WAAW,GAAG,IAAI,GAAG,CAAC;IACjF,OAAO,CACL,MAAM,KAAK,MAAM,GACb,kBAAkB,CAAC;MAAE,GAAG,OAAO;MAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE;MAAE,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG;IAAG,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAC/F,yBAAyB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAC9E,CAAC;EACH,CAAC;EAED,MAAM,iBAAiB,GAAG,MAAyB;IACjD,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC;IACjC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3B,OAAO;MACL,cAAc,EAAE,GAAG,WAAW,CAAC,KAAK,MAAM,WAAW,CAAC,MAAM,EAAE;MAC9D,WAAW,EAAE,qCAAqC,WAAW,CAAC,KAAK,MAAM,WAAW,CAAC,MAAM;IAC7F,CAAC;EACH,CAAC;EAED,MAAM,iBAAiB,GAAG,MAAyB;IACjD,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC;IACjC,IAAI,CAAC,cAAc,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,QAAQ,CAAC,CAAC,KAAK,GAAG;IAC/D,OAAO;MACL,IAAI,EAAE,KAAK;MACX,GAAG,EAAE,KAAK;MACV,KAAK,EAAE,eAAe,GAAG,GAAI,cAAc,CAAC,WAAW,GAAG,WAAW,CAAC,KAAK,GAAI,GAAG,GAAG,GAAG,MAAM;MAC9F,MAAM,EAAE,eAAe,GAAG,GAAI,cAAc,CAAC,YAAY,GAAG,WAAW,CAAC,MAAM,GAAI,GAAG,GAAG,GAAG,MAAM;MACjG,WAAW,EAAE,MAAM;MACnB,YAAY,EAAE,MAAM;MACpB,SAAS,EAAE,gCAAgC,QAAQ,CAAC,CAAC;IACvD,CAAC;EACH,CAAC;EAED,MAAM,SAAS,GAAG,MAAyB;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3B,OAAO;MACL,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG;MAC/B,GAAG,EAAE,GAAG,WAAW,CAAC,CAAC,GAAG,GAAG,GAAG;MAC9B,KAAK,EAAE,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG,GAAG;MACpC,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,GAAG;MACtC,YAAY,EAAE;IAChB,CAAC;EACH,CAAC;EAED,MAAM,iBAAiB,GAAG,MAAM,YAAY,CAAC,CAAC,KAAK,QAAQ;EAE3D,uBACc,8BAAqB,KAAK,CAAC,KAAK,IAAI,EAAE,SAAE,6BAE/C,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,CAAC,OAAO,CAAC,CAAC;IAAA;IAAA,IAAE,QAAQ;MAAA,gCAAU,QAAQ,CAAC,CAAC,CAAC,cAAc;IAAA;IAAA;MAAA,yBAChE,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,CAAC,KAAK,CAAC,CAAC;QAAA;QAAA,IAAE,QAAQ;UAAA,gCAA2C,KAAK,CAAC,CAAC;QAAA;QAAA;UAAA,yBAC7E,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,sBAAO,CAAC,CAAC,OAAI,IAAI,CAAC,CAAC;YAAA;YAAA;cAAA,kCAC4B,iBAAiB,CAAC,CAAC,kCAChE,OAAO,CAAC,CAAC,CAAE,GAAG,iDAAO,QAAQ,CAAC,CAAC,CAAC,WAAW,4BAA2B,iBAAiB,CAAC,CAAC,yCAGrF,YAAY,CAAC,CAAC,4BACnB,SAAS,CAAC,CAAC,8BAER,QAAQ,CAAC,CAAC,YAAG,SAAS,UAAG,CAAC,iDACxB,QAAQ,CAAC,CAAC,CAAC,QAAQ,4CAI9B,IAAI;gBAAA,IAAC,IAAI;kBAAA,OAAE,iBAAiB,CAAC,CAAC;gBAAA;gBAAA;kBAAA,yBAC5B,GAAG;oBAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;oBAAA,UAC/B,MAAM,2DAIS,MAAM,wDACP,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;sBAAE;oBAAO,CAAC,CAAC,4CACnC,QAAQ,CAAC,CAAC;kBAIvB;gBAAA;cAAA,gCAIN,OAAO,CAAC,OAAO;gBACd,IAAI;gBAAA;gBAAA,IAEJ,OAAO;kBAAA,OAAE,QAAQ,CAAC,CAAC,CAAC,WAAW;gBAAA;gBAAA;kBAAA,OACnB,QAAQ,CAAC,CAAC,CAAC,WAAW;gBAAA;gBAAA,IAClC,QAAQ;kBAAA,OAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gBAAA;gBACnD,OAAO,EAAE,WAAW;gBAAA;kBAAA;gBAAA;cAAA;YAAA;UAAA;QAAA;MAAA;IAAA;EAAA;AAWtC","ignoreList":[]}
@@ -0,0 +1,404 @@
1
+ import { memo as _$memo } from "solid-js/web";
2
+ import { createComponent as _$createComponent } from "solid-js/web";
3
+ import { ssr as _$ssr } from "solid-js/web";
4
+ import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
5
+ import { escape as _$escape } from "solid-js/web";
6
+ var _tmpl$ = ["<span", " hidden>", "</span>"],
7
+ _tmpl$2 = "<i class=\"ti ti-arrow-back-up\" aria-hidden=\"true\"></i>",
8
+ _tmpl$3 = "<i class=\"ti ti-eraser\" aria-hidden=\"true\"></i>",
9
+ _tmpl$4 = ["<span class=\"k2b-signature-input__placeholder\" aria-hidden=\"true\"><i class=\"ti ti-writing-sign\" aria-hidden=\"true\"></i>", "</span>"],
10
+ _tmpl$5 = ["<path", "></path>"],
11
+ _tmpl$6 = ["<svg class=\"k2b-signature-input__canvas\" role=\"img\" tabindex=\"-1\"", " viewBox=\"", "\" preserveAspectRatio=\"xMidYMid meet\"><g fill=\"currentColor\">", "", "</g></svg>"],
12
+ _tmpl$7 = ["<div", " class=\"k2b-signature-input\" role=\"group\"", ">", "<div class=\"k2b-signature-input__toolbar\">", "<div class=\"k2b-signature-input__actions\">", "", "</div></div><div class=\"k2b-signature-input__pad\"><span class=\"k2b-signature-input__line\" aria-hidden=\"true\"></span>", "</div></div>"],
13
+ _tmpl$8 = ["<input class=\"k2b-signature-input__name\" type=\"text\"", " autocomplete=\"name\" autocapitalize=\"words\" spellcheck=\"false\"", ">"],
14
+ _tmpl$9 = ["<input type=\"hidden\"", ">"];
15
+ import { createEffect, createSignal, For, on, Show, untrack } from "solid-js";
16
+ import { IconButton } from "../actions/Button";
17
+ import { SegmentedControl } from "../actions/SegmentedControl";
18
+ import { createFieldMeta, Field, fieldDescribedBy } from "../internal/field";
19
+ import { useUiMessages } from "../intl/messages";
20
+ import { commitFieldValue, resolveMaybeAccessor } from "./field-contract";
21
+ import { drawingToSvg, signatureName, strokeOutline, svgToDrawing, typedToSvg } from "./signature";
22
+ import { useSignatureMessages } from "./signature-messages";
23
+ /** Base stroke width in drawing units (CSS pixels at the time of drawing). */
24
+ const STROKE_SIZE = 3.2;
25
+ /** Points closer than this to the previous one add no shape, only path length. */
26
+ const MIN_POINT_DISTANCE = 1.2;
27
+ const EMPTY_SPACE = {
28
+ x: 0,
29
+ y: 0,
30
+ width: 600,
31
+ height: 200
32
+ };
33
+ const sameValue = (left, right) => left === right || left !== null && right !== null && left.kind === right.kind && left.svg === right.svg && (left.kind === "typed" && right.kind === "typed" ? left.name === right.name : true);
34
+ const drawingOf = value => (value?.kind === "drawn" ? svgToDrawing(value.svg) : null) ?? {
35
+ ...EMPTY_SPACE,
36
+ strokes: []
37
+ };
38
+ let measureContext;
39
+ const measureText = (text, font) => {
40
+ measureContext ??= document.createElement("canvas").getContext("2d");
41
+ if (!measureContext) return undefined;
42
+ measureContext.font = font;
43
+ return measureContext.measureText(text).width;
44
+ };
45
+
46
+ /**
47
+ * A signature field: draw with a finger, pen, or mouse, or type the name. The
48
+ * value is an SVG document plus how it was given; `signatureToPng` turns it
49
+ * into a bitmap. Legal evidence such as timestamps or hashes stays with the app.
50
+ */
51
+ export function SignatureInput(props) {
52
+ const messages = useUiMessages();
53
+ const text = useSignatureMessages();
54
+ const meta = createFieldMeta(props.id);
55
+ const requiredId = `${meta.controlId}-required`;
56
+ const value = () => resolveMaybeAccessor(props.value) ?? null;
57
+ const error = () => resolveMaybeAccessor(props.error);
58
+ const allowTyped = () => props.allowTyped !== false;
59
+ const editable = () => !props.disabled && !props.readOnly;
60
+ const initial = untrack(value);
61
+ const [mode, setMode] = createSignal(initial?.kind === "typed" ? "type" : "draw");
62
+ const [drawing, setDrawing] = createSignal(drawingOf(initial));
63
+ const [typedName, setTypedName] = createSignal(initial?.kind === "typed" ? initial.name : "");
64
+ const [live, setLive] = createSignal("");
65
+ let svg;
66
+ let nameInput;
67
+ let lastReported = initial;
68
+ const drawnValue = () => {
69
+ const markup = drawingToSvg(drawing());
70
+ return markup ? {
71
+ kind: "drawn",
72
+ svg: markup
73
+ } : null;
74
+ };
75
+ const typedValue = () => {
76
+ const name = signatureName(typedName());
77
+ if (!name) return null;
78
+ const family = nameInput ? getComputedStyle(nameInput).fontFamily : "cursive";
79
+ return {
80
+ kind: "typed",
81
+ name,
82
+ svg: typedToSvg(name, family, measureText)
83
+ };
84
+ };
85
+ const report = (next, commit) => {
86
+ if (sameValue(next, lastReported)) return;
87
+ lastReported = next;
88
+ if (commit) commitFieldValue(props, next);else props.onValueChange?.(next);
89
+ };
90
+ let stroke = null;
91
+ /** Drops the stroke in progress without keeping its ink. */
92
+ const abortStroke = () => {
93
+ if (!stroke) return;
94
+ const {
95
+ pointerId
96
+ } = stroke;
97
+ stroke = null;
98
+ setLive("");
99
+ if (svg?.hasPointerCapture(pointerId)) svg.releasePointerCapture(pointerId);
100
+ };
101
+ /** After Clear or the last Undo, keyboard focus moves from the now disabled button to the pad instead of the page. */
102
+ const keepFocus = button => {
103
+ if (button.matches(":focus-visible")) queueMicrotask(() => svg?.focus());
104
+ };
105
+
106
+ // A value the parent sets (a stored signature, another record, a reset to null) replaces both inputs, so nothing of an
107
+ // earlier signer stays behind the mode switch. Our own reports echo back unchanged.
108
+ createEffect(on(value, next => {
109
+ if (next === lastReported || sameValue(next, lastReported)) return;
110
+ lastReported = next;
111
+ abortStroke();
112
+ setDrawing(drawingOf(next));
113
+ setTypedName(next?.kind === "typed" ? next.name : "");
114
+ if (next) setMode(next.kind === "typed" ? "type" : "draw");
115
+ }, {
116
+ defer: true
117
+ }));
118
+ // A field that turns disabled or read-only, or leaves drawing, ends the stroke in progress without a value.
119
+ createEffect(() => {
120
+ if (!editable() || mode() !== "draw") abortStroke();
121
+ });
122
+ const switchMode = next => {
123
+ if (!editable() || next === mode()) return;
124
+ setMode(next);
125
+ report(next === "draw" ? drawnValue() : typedValue(), true);
126
+ };
127
+ const undo = event => {
128
+ if (!editable()) return;
129
+ setDrawing(current => ({
130
+ ...current,
131
+ strokes: current.strokes.slice(0, -1)
132
+ }));
133
+ if (drawing().strokes.length === 0) keepFocus(event.currentTarget);
134
+ report(drawnValue(), true);
135
+ };
136
+ const clear = event => {
137
+ if (!editable()) return;
138
+ abortStroke();
139
+ // Clear starts over in both modes. Without the Type option, a typed value it removes gives way to drawing.
140
+ setTypedName("");
141
+ setDrawing(current => ({
142
+ ...current,
143
+ strokes: []
144
+ }));
145
+ if (mode() === "type" && allowTyped()) {
146
+ nameInput?.focus();
147
+ } else {
148
+ setMode("draw");
149
+ keepFocus(event.currentTarget);
150
+ }
151
+ report(null, true);
152
+ };
153
+ const toPoint = event => {
154
+ const matrix = svg?.getScreenCTM();
155
+ if (!matrix) return null;
156
+ const point = new DOMPoint(event.clientX, event.clientY).matrixTransform(matrix.inverse());
157
+ return {
158
+ x: point.x,
159
+ y: point.y
160
+ };
161
+ };
162
+ const addPoint = (event, force = false) => {
163
+ if (!stroke) return;
164
+ const position = toPoint(event);
165
+ if (!position) return;
166
+ const previous = stroke.points[stroke.points.length - 1];
167
+ const distance = previous ? Math.hypot(position.x - previous.x, position.y - previous.y) : 0;
168
+ if (previous && distance < MIN_POINT_DISTANCE && !force) return;
169
+ let pressure;
170
+ if (event.pointerType === "pen" && event.pressure > 0) {
171
+ pressure = event.pressure;
172
+ } else {
173
+ // Without real pressure, faster movement draws a thinner line, as ink does.
174
+ const elapsed = Math.max(1, event.timeStamp - stroke.time);
175
+ const target = Math.min(1, Math.max(0.3, 1.1 - distance / elapsed * 0.3));
176
+ pressure = previous ? previous.pressure * 0.6 + target * 0.4 : 0.6;
177
+ }
178
+ stroke.time = event.timeStamp;
179
+ stroke.points.push({
180
+ ...position,
181
+ pressure
182
+ });
183
+ setLive(strokeOutline(stroke.points, STROKE_SIZE));
184
+ };
185
+ /**
186
+ * The drawing space after a stroke. It stays as it is while the ink lies inside it. Ink beyond it, drawn after the
187
+ * pad changed its shape (a rotated phone, a resized window, a drawing from another device), grows the space to the
188
+ * whole visible pad: the stored SVG then holds everything the signer saw, and the ink on the pad does not move.
189
+ */
190
+ const spaceAfter = points => {
191
+ const {
192
+ strokes: _,
193
+ ...space
194
+ } = drawing();
195
+ const matrix = svg?.getScreenCTM();
196
+ if (!svg || !matrix) return space;
197
+ const box = svg.getBoundingClientRect();
198
+ const inverse = matrix.inverse();
199
+ const start = new DOMPoint(box.left, box.top).matrixTransform(inverse);
200
+ const end = new DOMPoint(box.right, box.bottom).matrixTransform(inverse);
201
+ // Ink reaches half the widest stroke past its points; what lies outside the pad was never visible and does not count.
202
+ const reach = STROKE_SIZE / 2;
203
+ let left = end.x;
204
+ let top = end.y;
205
+ let right = start.x;
206
+ let bottom = start.y;
207
+ for (const point of points) {
208
+ left = Math.min(left, Math.max(start.x, point.x - reach));
209
+ top = Math.min(top, Math.max(start.y, point.y - reach));
210
+ right = Math.max(right, Math.min(end.x, point.x + reach));
211
+ bottom = Math.max(bottom, Math.min(end.y, point.y + reach));
212
+ }
213
+ if (left >= space.x && top >= space.y && right <= space.x + space.width && bottom <= space.y + space.height) return space;
214
+ const x = Math.min(space.x, start.x);
215
+ const y = Math.min(space.y, start.y);
216
+ return {
217
+ x,
218
+ y,
219
+ width: Math.max(space.x + space.width, end.x) - x,
220
+ height: Math.max(space.y + space.height, end.y) - y
221
+ };
222
+ };
223
+ const startStroke = event => {
224
+ // Only the primary contact draws: not a mouse's other buttons, a pen's barrel button, or its eraser.
225
+ if (!editable() || !svg || event.button !== 0) return;
226
+ // A pen takes over from a touch that is still down, such as a palm resting on a tablet.
227
+ if (stroke?.pointerType === "touch" && event.pointerType === "pen") abortStroke();
228
+ if (stroke) return;
229
+ event.preventDefault();
230
+ try {
231
+ // Capture keeps the stroke when the pointer leaves the pad; a pointer that already ended cannot be captured.
232
+ svg.setPointerCapture(event.pointerId);
233
+ } catch {}
234
+ if (drawing().strokes.length === 0) {
235
+ // An empty pad adopts its current size, so one drawing unit is one CSS pixel while drawing.
236
+ const box = svg.getBoundingClientRect();
237
+ setDrawing({
238
+ x: 0,
239
+ y: 0,
240
+ width: Math.max(1, box.width),
241
+ height: Math.max(1, box.height),
242
+ strokes: []
243
+ });
244
+ }
245
+ stroke = {
246
+ pointerId: event.pointerId,
247
+ pointerType: event.pointerType,
248
+ points: [],
249
+ time: event.timeStamp
250
+ };
251
+ addPoint(event, true);
252
+ };
253
+ const moveStroke = event => {
254
+ if (stroke?.pointerId !== event.pointerId) return;
255
+ event.preventDefault();
256
+ const events = event.getCoalescedEvents?.() ?? [];
257
+ for (const sample of events.length > 0 ? events : [event]) addPoint(sample);
258
+ };
259
+ const endStroke = event => {
260
+ if (!stroke || stroke.pointerId !== event.pointerId) return;
261
+ addPoint(event, false);
262
+ const {
263
+ points
264
+ } = stroke;
265
+ const outline = strokeOutline(points, STROKE_SIZE);
266
+ stroke = null;
267
+ setLive("");
268
+ if (!outline) return;
269
+ const space = spaceAfter(points);
270
+ setDrawing(current => ({
271
+ ...space,
272
+ strokes: [...current.strokes, outline]
273
+ }));
274
+ report(drawnValue(), true);
275
+ };
276
+ // A cancelled pointer (an OS gesture, palm rejection) or lost capture is not a finished stroke.
277
+ const cancelStroke = event => {
278
+ if (stroke?.pointerId === event.pointerId) abortStroke();
279
+ };
280
+ const empty = () => mode() === "draw" ? drawing().strokes.length === 0 && !live() : !signatureName(typedName());
281
+ const serialized = () => {
282
+ const current = value();
283
+ return current ? JSON.stringify(current) : "";
284
+ };
285
+ return _$createComponent(Field, {
286
+ get ["class"]() {
287
+ return props.class;
288
+ },
289
+ get label() {
290
+ return props.label;
291
+ },
292
+ get description() {
293
+ return props.description;
294
+ },
295
+ get error() {
296
+ return error();
297
+ },
298
+ meta: meta,
299
+ labelFor: false,
300
+ get required() {
301
+ return props.required;
302
+ },
303
+ get disabled() {
304
+ return props.disabled;
305
+ },
306
+ get children() {
307
+ return [_$ssr(_tmpl$7, _$ssrAttribute("id", _$escape(meta.controlId, true), false), _$ssrAttribute("aria-label", props.label ? _$escape(undefined, true) : _$escape(props["aria-label"], true), false) + _$ssrAttribute("aria-labelledby", props.label ? _$escape(meta.labelId, true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-describedby", _$escape([props.required ? requiredId : undefined, fieldDescribedBy(meta, props)].filter(Boolean).join(" ") || undefined, true), false) + _$ssrAttribute("aria-invalid", error() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-mode", _$escape(mode(), true), false) + _$ssrAttribute("data-empty", empty() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-invalid", error() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-disabled", props.disabled ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-readonly", props.readOnly ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
308
+ get when() {
309
+ return props.required;
310
+ },
311
+ get children() {
312
+ return _$ssr(_tmpl$, _$ssrAttribute("id", _$escape(requiredId, true), false), _$escape(messages().required));
313
+ }
314
+ })), _$escape(_$createComponent(Show, {
315
+ get when() {
316
+ return allowTyped();
317
+ },
318
+ get children() {
319
+ return _$createComponent(SegmentedControl, {
320
+ "class": "k2b-signature-input__modes",
321
+ size: "sm",
322
+ get ariaLabel() {
323
+ return text().method;
324
+ },
325
+ get options() {
326
+ return [{
327
+ value: "draw",
328
+ label: text().draw,
329
+ icon: "ti ti-signature"
330
+ }, {
331
+ value: "type",
332
+ label: text().type,
333
+ icon: "ti ti-keyboard"
334
+ }];
335
+ },
336
+ value: mode,
337
+ onValueChange: switchMode,
338
+ get disabled() {
339
+ return !editable();
340
+ }
341
+ });
342
+ }
343
+ })), _$escape(_$createComponent(IconButton, {
344
+ size: "sm",
345
+ variant: "ghost",
346
+ get label() {
347
+ return text().undo;
348
+ },
349
+ get ["data-hidden"]() {
350
+ return mode() === "type" ? "true" : undefined;
351
+ },
352
+ get disabled() {
353
+ return !editable() || mode() !== "draw" || drawing().strokes.length === 0;
354
+ },
355
+ onClick: undo,
356
+ get children() {
357
+ return _$ssr(_tmpl$2);
358
+ }
359
+ })), _$escape(_$createComponent(IconButton, {
360
+ size: "sm",
361
+ variant: "ghost",
362
+ get label() {
363
+ return messages().clear;
364
+ },
365
+ get disabled() {
366
+ return !editable() || empty();
367
+ },
368
+ onClick: clear,
369
+ get children() {
370
+ return _$ssr(_tmpl$3);
371
+ }
372
+ })), _$escape(_$createComponent(Show, {
373
+ get when() {
374
+ return mode() === "draw";
375
+ },
376
+ get fallback() {
377
+ return _$ssr(_tmpl$8, _$ssrAttribute("value", _$escape(typedName(), true), false) + _$ssrAttribute("placeholder", _$escape(text().typeName, true), false) + _$ssrAttribute("aria-label", _$escape(text().typeName, true), false) + _$ssrAttribute("aria-describedby", _$escape(fieldDescribedBy(meta, props), true), false) + _$ssrAttribute("aria-invalid", error() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("aria-required", _$escape(props.required || undefined, true), false), _$ssrAttribute("disabled", props.disabled, true) + _$ssrAttribute("readonly", _$escape(props.readOnly || !allowTyped(), true), false));
378
+ },
379
+ get children() {
380
+ return [_$ssr(_tmpl$4, _$escape(text().signHere)), _$ssr(_tmpl$6, _$ssrAttribute("aria-label", drawing().strokes.length > 0 ? _$escape(text().drawn, true) : _$escape(text().drawArea, true), false), `${_$escape(drawing().x, true)} ${_$escape(drawing().y, true)} ${_$escape(drawing().width, true)} ${_$escape(drawing().height, true)}`, _$escape(_$createComponent(For, {
381
+ get each() {
382
+ return drawing().strokes;
383
+ },
384
+ children: outline => _$ssr(_tmpl$5, _$ssrAttribute("d", _$escape(outline, true), false))
385
+ })), _$escape(_$createComponent(Show, {
386
+ get when() {
387
+ return live();
388
+ },
389
+ get children() {
390
+ return _$ssr(_tmpl$5, _$ssrAttribute("d", _$escape(live(), true), false));
391
+ }
392
+ })))];
393
+ }
394
+ }))), _$createComponent(Show, {
395
+ get when() {
396
+ return props.name;
397
+ },
398
+ children: name => _$ssr(_tmpl$9, _$ssrAttribute("name", _$escape(name(), true), false) + _$ssrAttribute("value", _$escape(serialized(), true), false))
399
+ })];
400
+ }
401
+ });
402
+ }
403
+ export default SignatureInput;
404
+ //# sourceMappingURL=SignatureInput.js.map