@windwalker-io/unicorn-next 0.1.18 → 0.1.21

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 (108) hide show
  1. package/dist/chunks/_arrayPush.js +325 -108
  2. package/dist/chunks/_arrayPush.js.map +1 -1
  3. package/dist/chunks/_baseRest.js +155 -60
  4. package/dist/chunks/_baseRest.js.map +1 -1
  5. package/dist/chunks/_baseUnary.js +463 -0
  6. package/dist/chunks/_baseUnary.js.map +1 -0
  7. package/dist/chunks/_getPrototype.js +292 -100
  8. package/dist/chunks/_getPrototype.js.map +1 -1
  9. package/dist/chunks/alert-adapter.js +29 -0
  10. package/dist/chunks/alert-adapter.js.map +1 -0
  11. package/dist/chunks/alert.js +21 -0
  12. package/dist/chunks/alert.js.map +1 -0
  13. package/dist/chunks/arr.js +24 -0
  14. package/dist/chunks/arr.js.map +1 -0
  15. package/dist/chunks/button-radio.js +127 -145
  16. package/dist/chunks/button-radio.js.map +1 -1
  17. package/dist/chunks/checkboxes-multi-select.js +44 -43
  18. package/dist/chunks/checkboxes-multi-select.js.map +1 -1
  19. package/dist/chunks/chunk.js +24 -0
  20. package/dist/chunks/cloneDeep.js +679 -212
  21. package/dist/chunks/cloneDeep.js.map +1 -1
  22. package/dist/chunks/cropper.min.js +6 -5
  23. package/dist/chunks/cropper.min.js.map +1 -1
  24. package/dist/chunks/crypto.js +26 -0
  25. package/dist/chunks/crypto.js.map +1 -0
  26. package/dist/chunks/data.js +49 -0
  27. package/dist/chunks/data.js.map +1 -0
  28. package/dist/chunks/dom.js +128 -0
  29. package/dist/chunks/dom.js.map +1 -0
  30. package/dist/chunks/events.js +270 -0
  31. package/dist/chunks/events.js.map +1 -0
  32. package/dist/chunks/field-cascade-select.js +207 -250
  33. package/dist/chunks/field-cascade-select.js.map +1 -1
  34. package/dist/chunks/field-file-drag.js +175 -209
  35. package/dist/chunks/field-file-drag.js.map +1 -1
  36. package/dist/chunks/field-flatpickr.js +94 -898
  37. package/dist/chunks/field-flatpickr.js.map +1 -1
  38. package/dist/chunks/field-modal-select.js +728 -467
  39. package/dist/chunks/field-modal-select.js.map +1 -1
  40. package/dist/chunks/field-modal-tree.js +771 -766
  41. package/dist/chunks/field-modal-tree.js.map +1 -1
  42. package/dist/chunks/field-multi-uploader.js +249 -256
  43. package/dist/chunks/field-multi-uploader.js.map +1 -1
  44. package/dist/chunks/field-repeatable.js +111 -127
  45. package/dist/chunks/field-repeatable.js.map +1 -1
  46. package/dist/chunks/field-single-image-drag.js +286 -338
  47. package/dist/chunks/field-single-image-drag.js.map +1 -1
  48. package/dist/chunks/form.js +146 -159
  49. package/dist/chunks/form.js.map +1 -1
  50. package/dist/chunks/grid.js +349 -418
  51. package/dist/chunks/grid.js.map +1 -1
  52. package/dist/chunks/helper.js +39 -0
  53. package/dist/chunks/helper.js.map +1 -0
  54. package/dist/chunks/http-client.js +221 -211
  55. package/dist/chunks/http-client.js.map +1 -1
  56. package/dist/chunks/iframe-modal.js +95 -115
  57. package/dist/chunks/iframe-modal.js.map +1 -1
  58. package/dist/chunks/keep-tab.js +92 -101
  59. package/dist/chunks/keep-tab.js.map +1 -1
  60. package/dist/chunks/lang.js +250 -0
  61. package/dist/chunks/lang.js.map +1 -0
  62. package/dist/chunks/legacy.js +197 -201
  63. package/dist/chunks/legacy.js.map +1 -1
  64. package/dist/chunks/list-dependent.js +195 -228
  65. package/dist/chunks/list-dependent.js.map +1 -1
  66. package/dist/chunks/loader.js +106 -0
  67. package/dist/chunks/loader.js.map +1 -0
  68. package/dist/chunks/monthSelect.js +251 -0
  69. package/dist/chunks/monthSelect.js.map +1 -0
  70. package/dist/chunks/router.js +111 -0
  71. package/dist/chunks/router.js.map +1 -0
  72. package/dist/chunks/s3-multipart-uploader.js +183 -210
  73. package/dist/chunks/s3-multipart-uploader.js.map +1 -1
  74. package/dist/chunks/s3-uploader.js +106 -128
  75. package/dist/chunks/s3-uploader.js.map +1 -1
  76. package/dist/chunks/show-on.js +358 -205
  77. package/dist/chunks/show-on.js.map +1 -1
  78. package/dist/chunks/timing.js +10 -0
  79. package/dist/chunks/timing.js.map +1 -0
  80. package/dist/chunks/tinymce.js +153 -203
  81. package/dist/chunks/tinymce.js.map +1 -1
  82. package/dist/chunks/ui-bootstrap5.js +58 -72
  83. package/dist/chunks/ui-bootstrap5.js.map +1 -1
  84. package/dist/chunks/ui.js +320 -0
  85. package/dist/chunks/ui.js.map +1 -0
  86. package/dist/chunks/unicorn.js.map +1 -1
  87. package/dist/chunks/useQueue.js +111 -0
  88. package/dist/chunks/useQueue.js.map +1 -0
  89. package/dist/chunks/useStack.js +76 -0
  90. package/dist/chunks/useStack.js.map +1 -0
  91. package/dist/chunks/validation.js +761 -853
  92. package/dist/chunks/validation.js.map +1 -1
  93. package/dist/editor.css +1 -1
  94. package/dist/index.d.ts +27 -15
  95. package/dist/multi-level-menu.css +1 -1
  96. package/dist/switcher.css +1 -1
  97. package/dist/unicorn.js +805 -130
  98. package/dist/unicorn.js.map +1 -1
  99. package/package.json +3 -3
  100. package/src/composable/useBsModalAlert.ts +92 -12
  101. package/src/composable/useHttp.ts +13 -1
  102. package/src/module/s3-uploader.ts +1 -1
  103. package/src/service/ui.ts +31 -15
  104. package/vite.config.ts +5 -1
  105. package/dist/chunks/_commonjsHelpers.js +0 -7
  106. package/dist/chunks/index.js +0 -314
  107. package/dist/chunks/isArguments.js +0 -146
  108. package/dist/chunks/unicorn.js +0 -2580
@@ -1 +1 @@
1
- {"version":3,"file":"field-single-image-drag.js","sources":["../../src/module/field-single-image-drag.ts"],"sourcesContent":["\nimport { useHttpClient } from '../composable';\nimport { __, injectCssToDocument, selectAll, simpleAlert } from '../service';\nimport { mergeDeep } from '../utilities';\nimport css from '../../scss/field/single-image-drag.scss?inline';\nimport { Modal } from 'bootstrap';\nimport type Cropper from 'cropperjs';\nimport { ApiReturn } from './http-client';\n\nexport interface SingleImageDragOptions {\n accept: string | string[];\n ajax_url?: string;\n crop: boolean;\n width: number;\n height: number;\n max_width?: number;\n min_width?: number;\n max_height?: number;\n min_height?: number;\n modalTarget: string;\n}\n\nconst defaultOptions: Partial<SingleImageDragOptions> = {\n accept: [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/avif',\n 'image/gif',\n ],\n crop: false,\n width: 800,\n height: 800,\n};\n\nexport class SingleImageDragElement extends HTMLElement {\n static is = 'uni-sid';\n\n currentImage = '';\n currentFile: File | undefined = undefined;\n lastZoom = 0;\n valueBackup = '';\n\n private options!: SingleImageDragOptions;\n private valueInput!: HTMLInputElement;\n private fileInput!: HTMLInputElement;\n private selectButton: HTMLButtonElement | null = null;\n private pasteButton: HTMLButtonElement | null = null;\n private dragarea: HTMLDivElement | null = null;\n private previewImage!: HTMLImageElement;\n private removeCheckbox!: HTMLInputElement;\n private modalElement!: HTMLDivElement;\n private modal!: Modal;\n private cropContainer!: HTMLDivElement;\n private savebutton!: HTMLButtonElement;\n private modalToolbarButtons!: NodeListOf<HTMLButtonElement>;\n private cropper!: Cropper;\n\n constructor() {\n super();\n }\n\n connectedCallback() {\n this.options = mergeDeep(\n {},\n defaultOptions,\n JSON.parse(this.getAttribute('options') || '{}')\n );\n\n this.valueInput = this.querySelector<HTMLInputElement>('[data-field-input]')!;\n this.fileInput = this.querySelector<HTMLInputElement>('[data-sid=file]')!;\n this.selectButton = this.querySelector<HTMLButtonElement>('[data-sid=select]')!;\n this.pasteButton = this.querySelector<HTMLButtonElement>('[data-sid=paste]')!;\n this.dragarea = this.querySelector<HTMLDivElement>('[data-sid=dragarea]');\n this.previewImage = this.querySelector<HTMLImageElement>('[data-sid=preview]')!;\n this.removeCheckbox = this.querySelector<HTMLInputElement>('[data-sid=remove]')!;\n\n this.modalElement = document.querySelector<HTMLDivElement>(this.options.modalTarget)!;\n this.modal = Modal.getOrCreateInstance(this.modalElement);\n this.cropContainer = this.modalElement.querySelector<HTMLDivElement>('[data-sid=\"crop-container\"]')!;\n this.savebutton = this.modalElement.querySelector<HTMLButtonElement>('[data-sid=save-button]')!;\n this.modalToolbarButtons = this.modalElement.querySelectorAll<HTMLButtonElement>('[data-sid-toolbar]');\n\n const modalShown = async () => {\n const cropper = await this.getCropper();\n cropper.replace(this.currentImage);\n this.cropContainer.style.visibility = '';\n this.currentImage = '';\n };\n\n this.modalElement.addEventListener('shown.bs.modal', modalShown.bind(this));\n\n this.savebutton.addEventListener('click', () => {\n this.saveCropped();\n this.modal.hide();\n });\n\n this.bindEvents();\n\n this.style.visibility = '';\n }\n\n bindEvents() {\n if (this.dragarea) {\n this.dragarea.addEventListener('dragover', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.add('hover');\n });\n\n this.dragarea.addEventListener('dragleave', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.remove('hover');\n });\n\n this.dragarea.addEventListener('drop', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.remove('hover');\n\n const files = (event.target as HTMLInputElement).files || event.dataTransfer?.files || [];\n this.handleFileSelect(files[0]);\n });\n }\n\n // Select button\n this.selectButton?.addEventListener('click', () => {\n const input = document.createElement('input');\n input.setAttribute('type', 'file');\n input.setAttribute('accept', this.getInputAccept());\n input.style.display = 'none';\n input.addEventListener('change', (e) => {\n this.handleFileSelect(input.files![0]!);\n\n input.remove();\n });\n\n document.body.appendChild(input);\n input.click();\n });\n\n this.pasteButton?.addEventListener('click', () => {\n navigator.clipboard.read().then((items) => {\n let types = items[0].types;\n\n if (types.length === 0) {\n this.alert('This browser unable to get clipboard data.');\n return;\n }\n\n types = types.slice().sort();\n\n const type = types[0];\n\n items[0].getType(type).then((blob) => {\n this.handleFileSelect(new File([ blob ], 'image.png', { type }));\n });\n });\n });\n\n // Delete\n this.removeCheckbox?.addEventListener('click', () => {\n if (this.removeCheckbox.checked) {\n this.valueBackup = this.valueInput.value;\n this.valueInput.value = '';\n } else {\n this.valueInput.value = this.valueBackup;\n this.valueBackup = '';\n }\n });\n\n // Zoom slider\n selectAll(this.modalToolbarButtons, (button) => {\n button.addEventListener('click', (event) => {\n this.toolbarClicked(button, event);\n });\n });\n }\n\n getInputAccept() {\n let accept = this.options.accept;\n\n if (Array.isArray(accept)) {\n accept = accept.join(',');\n }\n\n return accept;\n }\n\n handleFileSelect(file: File) {\n if (!this.checkFile(file)) {\n return;\n }\n\n if (this.options.crop) {\n const reader = new FileReader();\n\n reader.addEventListener('load', (event) => {\n this.cropContainer.style.visibility = 'hidden';\n this.currentImage = event.target!.result as string;\n this.currentFile = file;\n\n // After modal shown, cropper will auto load.\n this.modal.show();\n });\n\n reader.readAsDataURL(file);\n return;\n }\n\n this.saveImage(file);\n }\n\n async saveCropped() {\n const Cropper = await this.getCropper();\n\n Cropper.getCroppedCanvas({\n width: this.options.width,\n height: this.options.height,\n imageSmoothingEnabled: true\n })\n .toBlob((blob) => {\n const file = new File([ blob! ], this.currentFile!.name, { type: 'image/png' });\n this.saveImage(file);\n }, 'image/png');\n }\n\n async getCropper() {\n if (this.cropper) {\n return this.cropper;\n }\n\n const Cropper = await loadCropper();\n\n return this.cropper = new Cropper(this.cropContainer.querySelector('img')!, {\n aspectRatio: this.options.width / this.options.height,\n autoCropArea: 1,\n viewMode: 1,\n dragMode: 'move',\n cropBoxMovable: false,\n cropBoxResizable: false,\n ready: (e) => {\n //\n },\n });\n }\n\n async toolbarClicked(button: HTMLButtonElement, event: MouseEvent) {\n const cropper = await this.getCropper();\n\n const data = cropper.getData();\n\n switch (button.dataset.sidToolbar) {\n case 'zoom-in':\n cropper.zoom(0.1);\n break;\n\n case 'zoom-out':\n cropper.zoom(-0.1);\n break;\n\n case 'rotate-left':\n cropper.rotate(-90);\n break;\n\n case 'rotate-right':\n cropper.rotate(90);\n break;\n\n case 'scale-x':\n cropper.scaleX(-data.scaleX);\n break;\n\n case 'scale-y':\n cropper.scaleY(-data.scaleY);\n break;\n }\n }\n\n checkFile(file: File): boolean {\n let accept = this.options.accept;\n\n if (typeof accept === 'string') {\n accept = accept.split(',').map(v => v.trim());\n }\n\n if (!accept.length) {\n return true;\n }\n\n let allow = false;\n\n for (const type of accept) {\n if (type.indexOf('/') !== -1) {\n allow = allow || this.compareMimeType(type, file.type);\n } else {\n allow = allow || type.toLowerCase() === getFileExtension(file)?.toLowerCase();\n }\n }\n\n if (allow) {\n return true;\n }\n\n this.alert(\n __('unicorn.field.sid.message.invalid.image.title'),\n __('unicorn.field.sid.message.invalid.image.desc'),\n 'error'\n );\n\n return false;\n }\n\n compareMimeType(accept: string, mime: string) {\n const accept2 = accept.split('/');\n const mime2 = mime.split('/');\n\n if (accept2[1] === '*') {\n return accept2[0] === mime2[0];\n }\n\n return accept === mime;\n }\n\n checkSize(image: HTMLImageElement): boolean {\n try {\n if (this.options.max_width && this.options.max_width < image.width) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.width', this.options.max_width));\n }\n\n if (this.options.min_width && this.options.min_width > image.width) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.width', this.options.min_width));\n }\n\n if (this.options.max_height && this.options.max_height < image.height) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.height', this.options.max_height));\n }\n\n if (this.options.min_height && this.options.min_height > image.height) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.height', this.options.min_height));\n }\n } catch (e) {\n this.alert(\n __('unicorn.field.sid.message.invalid.size.title'),\n (e as Error).message,\n 'error'\n );\n\n return false;\n }\n\n return true;\n }\n\n alert(title: string, text = '', type = 'info') {\n return simpleAlert(title, text, type);\n }\n\n async saveImage(file: File) {\n if (this.options.ajax_url) {\n const loading = this.querySelector<HTMLImageElement>('[data-sid=file-uploading]')!;\n\n this.previewImage.src = '';\n this.previewImage.style.display = 'none';\n loading.style.display = 'flex';\n\n try {\n const res = await this.uploadImage(file);\n\n this.storeValue(res.data.data.url, res.data.data.url);\n } catch (e) {\n console.error(e);\n simpleAlert((e as Error).message);\n return;\n } finally {\n loading.style.display = 'none';\n }\n\n return;\n }\n\n // @see https://stackoverflow.com/a/47172409\n // @see https://stackoverflow.com/a/47522812\n const dt = new DataTransfer();\n dt.items.add(file);\n\n // No required for value input to remove validation message\n this.valueInput.required = false;\n\n this.fileInput.files = dt.files;\n this.fileInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.fileInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\n\n this.storeValue('', URL.createObjectURL(file));\n }\n\n async uploadImage(file: File) {\n const formData = new FormData();\n formData.append('file', file);\n\n const { post } = await useHttpClient();\n\n return post<ApiReturn<{ url: string; }>>(this.options.ajax_url!, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data'\n }\n });\n }\n\n storeValue(url: string, preview: string) {\n this.previewImage.src = preview;\n this.previewImage.style.display = 'inline-block';\n\n // Make delete box unchecked\n if (this.removeCheckbox) {\n this.removeCheckbox.checked = false;\n }\n\n if (url) {\n this.valueInput.value = url;\n }\n\n // Trigger change\n this.previewImage.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.valueInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.valueInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\n }\n}\n\n// Promise.all([\n// import('@cropperjs/cropper.min.js'),\n// import('@cropperjs/cropper.css'),\n// ])\n// .then((service) => {\n// const styleSheet = service[1].default;\n// document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleSheet];\n// });\n\nfunction getFileExtension(file: File): string | undefined {\n const parts = file.name.split('.');\n if (parts.length > 1) {\n return parts.pop();\n }\n return undefined;\n}\n\nlet loadingCropper: Promise<any>;\n\nasync function loadCropper(): Promise<typeof Cropper> {\n loadingCropper ??= Promise.all([\n import('cropperjs'),\n import('cropperjs/dist/cropper.min.css?inline').then(({ default: css }) => {\n injectCssToDocument(css);\n })\n ]);\n\n const module = (await loadingCropper)[0];\n\n return module.default;\n}\n\nasync function init() {\n injectCssToDocument(css);\n\n customElements.define(SingleImageDragElement.is, SingleImageDragElement);\n\n await loadCropper();\n}\n\nexport const ready = init();\n\nexport interface SingleImageDragModule {\n SingleImageDragElement: typeof SingleImageDragElement;\n ready: typeof ready;\n}\n"],"names":["css"],"mappings":"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"}
1
+ {"version":3,"file":"field-single-image-drag.js","names":[],"sources":["../../scss/field/single-image-drag.scss?inline","../../src/module/field-single-image-drag.ts"],"sourcesContent":["// Part of starter file.\n\n.c-sid-default {\n &__left-col {\n width: 30%;\n margin-right: 15px;\n justify-content: center;\n }\n\n &__left-col img {\n max-height: 250px;\n }\n\n &__right-col {\n overflow: hidden;\n }\n\n &__dragarea {\n font-weight: bold;\n text-align: center;\n padding: 9% 0;\n color: #ccc;\n border: 2px dashed #ccc;\n border-radius: 7px;\n cursor: default;\n\n &.hover {\n color: #333;\n border-color: #333;\n background-color: #f9f9f9;\n }\n }\n\n &__img-loader {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 180px;\n }\n\n &__size-info {\n margin-top: 5px;\n font-size: 13px;\n }\n\n &__remove {\n margin-left: 5px;\n }\n\n &__modal .btn {\n position: relative;\n }\n}\n\n.c-sid-modal {\n .modal-body {\n position: relative;\n }\n\n &__content {\n position: relative;\n z-index: 3;\n }\n\n &__loading {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 1;\n }\n\n &__img-container {\n\n }\n}\n\n// A workaround for form validation\n.is-invalid[uni-field-validate] {\n > uni-sid ~ [data-field-error] {\n display: block;\n }\n}\n","\nimport { useHttpClient } from '../composable';\nimport { __, injectCssToDocument, selectAll, simpleAlert } from '../service';\nimport { mergeDeep } from '../utilities';\nimport css from '../../scss/field/single-image-drag.scss?inline';\nimport { Modal } from 'bootstrap';\nimport type Cropper from 'cropperjs';\nimport { ApiReturn } from './http-client';\n\nexport interface SingleImageDragOptions {\n accept: string | string[];\n ajax_url?: string;\n crop: boolean;\n width: number;\n height: number;\n max_width?: number;\n min_width?: number;\n max_height?: number;\n min_height?: number;\n modalTarget: string;\n}\n\nconst defaultOptions: Partial<SingleImageDragOptions> = {\n accept: [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/avif',\n 'image/gif',\n ],\n crop: false,\n width: 800,\n height: 800,\n};\n\nexport class SingleImageDragElement extends HTMLElement {\n static is = 'uni-sid';\n\n currentImage = '';\n currentFile: File | undefined = undefined;\n lastZoom = 0;\n valueBackup = '';\n\n private options!: SingleImageDragOptions;\n private valueInput!: HTMLInputElement;\n private fileInput!: HTMLInputElement;\n private selectButton: HTMLButtonElement | null = null;\n private pasteButton: HTMLButtonElement | null = null;\n private dragarea: HTMLDivElement | null = null;\n private previewImage!: HTMLImageElement;\n private removeCheckbox!: HTMLInputElement;\n private modalElement!: HTMLDivElement;\n private modal!: Modal;\n private cropContainer!: HTMLDivElement;\n private savebutton!: HTMLButtonElement;\n private modalToolbarButtons!: NodeListOf<HTMLButtonElement>;\n private cropper!: Cropper;\n\n constructor() {\n super();\n }\n\n connectedCallback() {\n this.options = mergeDeep(\n {},\n defaultOptions,\n JSON.parse(this.getAttribute('options') || '{}')\n );\n\n this.valueInput = this.querySelector<HTMLInputElement>('[data-field-input]')!;\n this.fileInput = this.querySelector<HTMLInputElement>('[data-sid=file]')!;\n this.selectButton = this.querySelector<HTMLButtonElement>('[data-sid=select]')!;\n this.pasteButton = this.querySelector<HTMLButtonElement>('[data-sid=paste]')!;\n this.dragarea = this.querySelector<HTMLDivElement>('[data-sid=dragarea]');\n this.previewImage = this.querySelector<HTMLImageElement>('[data-sid=preview]')!;\n this.removeCheckbox = this.querySelector<HTMLInputElement>('[data-sid=remove]')!;\n\n this.modalElement = document.querySelector<HTMLDivElement>(this.options.modalTarget)!;\n this.modal = Modal.getOrCreateInstance(this.modalElement);\n this.cropContainer = this.modalElement.querySelector<HTMLDivElement>('[data-sid=\"crop-container\"]')!;\n this.savebutton = this.modalElement.querySelector<HTMLButtonElement>('[data-sid=save-button]')!;\n this.modalToolbarButtons = this.modalElement.querySelectorAll<HTMLButtonElement>('[data-sid-toolbar]');\n\n const modalShown = async () => {\n const cropper = await this.getCropper();\n cropper.replace(this.currentImage);\n this.cropContainer.style.visibility = '';\n this.currentImage = '';\n };\n\n this.modalElement.addEventListener('shown.bs.modal', modalShown.bind(this));\n\n this.savebutton.addEventListener('click', () => {\n this.saveCropped();\n this.modal.hide();\n });\n\n this.bindEvents();\n\n this.style.visibility = '';\n }\n\n bindEvents() {\n if (this.dragarea) {\n this.dragarea.addEventListener('dragover', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.add('hover');\n });\n\n this.dragarea.addEventListener('dragleave', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.remove('hover');\n });\n\n this.dragarea.addEventListener('drop', (event) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.dragarea!.classList.remove('hover');\n\n const files = (event.target as HTMLInputElement).files || event.dataTransfer?.files || [];\n this.handleFileSelect(files[0]);\n });\n }\n\n // Select button\n this.selectButton?.addEventListener('click', () => {\n const input = document.createElement('input');\n input.setAttribute('type', 'file');\n input.setAttribute('accept', this.getInputAccept());\n input.style.display = 'none';\n input.addEventListener('change', (e) => {\n this.handleFileSelect(input.files![0]!);\n\n input.remove();\n });\n\n document.body.appendChild(input);\n input.click();\n });\n\n this.pasteButton?.addEventListener('click', () => {\n navigator.clipboard.read().then((items) => {\n let types = items[0].types;\n\n if (types.length === 0) {\n this.alert('This browser unable to get clipboard data.');\n return;\n }\n\n types = types.slice().sort();\n\n const type = types[0];\n\n items[0].getType(type).then((blob) => {\n this.handleFileSelect(new File([ blob ], 'image.png', { type }));\n });\n });\n });\n\n // Delete\n this.removeCheckbox?.addEventListener('click', () => {\n if (this.removeCheckbox.checked) {\n this.valueBackup = this.valueInput.value;\n this.valueInput.value = '';\n } else {\n this.valueInput.value = this.valueBackup;\n this.valueBackup = '';\n }\n });\n\n // Zoom slider\n selectAll(this.modalToolbarButtons, (button) => {\n button.addEventListener('click', (event) => {\n this.toolbarClicked(button, event);\n });\n });\n }\n\n getInputAccept() {\n let accept = this.options.accept;\n\n if (Array.isArray(accept)) {\n accept = accept.join(',');\n }\n\n return accept;\n }\n\n handleFileSelect(file: File) {\n if (!this.checkFile(file)) {\n return;\n }\n\n if (this.options.crop) {\n const reader = new FileReader();\n\n reader.addEventListener('load', (event) => {\n this.cropContainer.style.visibility = 'hidden';\n this.currentImage = event.target!.result as string;\n this.currentFile = file;\n\n // After modal shown, cropper will auto load.\n this.modal.show();\n });\n\n reader.readAsDataURL(file);\n return;\n }\n\n this.saveImage(file);\n }\n\n async saveCropped() {\n const Cropper = await this.getCropper();\n\n Cropper.getCroppedCanvas({\n width: this.options.width,\n height: this.options.height,\n imageSmoothingEnabled: true\n })\n .toBlob((blob) => {\n const file = new File([ blob! ], this.currentFile!.name, { type: 'image/png' });\n this.saveImage(file);\n }, 'image/png');\n }\n\n async getCropper() {\n if (this.cropper) {\n return this.cropper;\n }\n\n const Cropper = await loadCropper();\n\n return this.cropper = new Cropper(this.cropContainer.querySelector('img')!, {\n aspectRatio: this.options.width / this.options.height,\n autoCropArea: 1,\n viewMode: 1,\n dragMode: 'move',\n cropBoxMovable: false,\n cropBoxResizable: false,\n ready: (e) => {\n //\n },\n });\n }\n\n async toolbarClicked(button: HTMLButtonElement, event: MouseEvent) {\n const cropper = await this.getCropper();\n\n const data = cropper.getData();\n\n switch (button.dataset.sidToolbar) {\n case 'zoom-in':\n cropper.zoom(0.1);\n break;\n\n case 'zoom-out':\n cropper.zoom(-0.1);\n break;\n\n case 'rotate-left':\n cropper.rotate(-90);\n break;\n\n case 'rotate-right':\n cropper.rotate(90);\n break;\n\n case 'scale-x':\n cropper.scaleX(-data.scaleX);\n break;\n\n case 'scale-y':\n cropper.scaleY(-data.scaleY);\n break;\n }\n }\n\n checkFile(file: File): boolean {\n let accept = this.options.accept;\n\n if (typeof accept === 'string') {\n accept = accept.split(',').map(v => v.trim());\n }\n\n if (!accept.length) {\n return true;\n }\n\n let allow = false;\n\n for (const type of accept) {\n if (type.indexOf('/') !== -1) {\n allow = allow || this.compareMimeType(type, file.type);\n } else {\n allow = allow || type.toLowerCase() === getFileExtension(file)?.toLowerCase();\n }\n }\n\n if (allow) {\n return true;\n }\n\n this.alert(\n __('unicorn.field.sid.message.invalid.image.title'),\n __('unicorn.field.sid.message.invalid.image.desc'),\n 'error'\n );\n\n return false;\n }\n\n compareMimeType(accept: string, mime: string) {\n const accept2 = accept.split('/');\n const mime2 = mime.split('/');\n\n if (accept2[1] === '*') {\n return accept2[0] === mime2[0];\n }\n\n return accept === mime;\n }\n\n checkSize(image: HTMLImageElement): boolean {\n try {\n if (this.options.max_width && this.options.max_width < image.width) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.width', this.options.max_width));\n }\n\n if (this.options.min_width && this.options.min_width > image.width) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.width', this.options.min_width));\n }\n\n if (this.options.max_height && this.options.max_height < image.height) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.height', this.options.max_height));\n }\n\n if (this.options.min_height && this.options.min_height > image.height) {\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.height', this.options.min_height));\n }\n } catch (e) {\n this.alert(\n __('unicorn.field.sid.message.invalid.size.title'),\n (e as Error).message,\n 'error'\n );\n\n return false;\n }\n\n return true;\n }\n\n alert(title: string, text = '', type = 'info') {\n return simpleAlert(title, text, type);\n }\n\n async saveImage(file: File) {\n if (this.options.ajax_url) {\n const loading = this.querySelector<HTMLImageElement>('[data-sid=file-uploading]')!;\n\n this.previewImage.src = '';\n this.previewImage.style.display = 'none';\n loading.style.display = 'flex';\n\n try {\n const res = await this.uploadImage(file);\n\n this.storeValue(res.data.data.url, res.data.data.url);\n } catch (e) {\n console.error(e);\n simpleAlert((e as Error).message);\n return;\n } finally {\n loading.style.display = 'none';\n }\n\n return;\n }\n\n // @see https://stackoverflow.com/a/47172409\n // @see https://stackoverflow.com/a/47522812\n const dt = new DataTransfer();\n dt.items.add(file);\n\n // No required for value input to remove validation message\n this.valueInput.required = false;\n\n this.fileInput.files = dt.files;\n this.fileInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.fileInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\n\n this.storeValue('', URL.createObjectURL(file));\n }\n\n async uploadImage(file: File) {\n const formData = new FormData();\n formData.append('file', file);\n\n const { post } = await useHttpClient();\n\n return post<ApiReturn<{ url: string; }>>(this.options.ajax_url!, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data'\n }\n });\n }\n\n storeValue(url: string, preview: string) {\n this.previewImage.src = preview;\n this.previewImage.style.display = 'inline-block';\n\n // Make delete box unchecked\n if (this.removeCheckbox) {\n this.removeCheckbox.checked = false;\n }\n\n if (url) {\n this.valueInput.value = url;\n }\n\n // Trigger change\n this.previewImage.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.valueInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\n this.valueInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\n }\n}\n\n// Promise.all([\n// import('@cropperjs/cropper.min.js'),\n// import('@cropperjs/cropper.css'),\n// ])\n// .then((service) => {\n// const styleSheet = service[1].default;\n// document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleSheet];\n// });\n\nfunction getFileExtension(file: File): string | undefined {\n const parts = file.name.split('.');\n if (parts.length > 1) {\n return parts.pop();\n }\n return undefined;\n}\n\nlet loadingCropper: Promise<any>;\n\nasync function loadCropper(): Promise<typeof Cropper> {\n loadingCropper ??= Promise.all([\n import('cropperjs'),\n import('cropperjs/dist/cropper.min.css?inline').then(({ default: css }) => {\n injectCssToDocument(css);\n })\n ]);\n\n const module = (await loadingCropper)[0];\n\n return module.default;\n}\n\nasync function init() {\n injectCssToDocument(css);\n\n customElements.define(SingleImageDragElement.is, SingleImageDragElement);\n\n await loadCropper();\n}\n\nexport const ready = init();\n\nexport interface SingleImageDragModule {\n SingleImageDragElement: typeof SingleImageDragElement;\n ready: typeof ready;\n}\n"],"mappings":"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"}
@@ -1,160 +1,147 @@
1
- import { o as useSystemUri, ae as data, l as loadAlpine } from "./unicorn.js";
2
- class UnicornFormElement {
3
- element;
4
- options;
5
- constructor(selector, element, options = {}) {
6
- if (!element) {
7
- element = document.createElement("form");
8
- if (typeof selector === "string" && selector.startsWith("#")) {
9
- element.setAttribute("id", selector.substring(1));
10
- element.setAttribute("name", selector.substring(1));
11
- }
12
- element.setAttribute("method", "post");
13
- element.setAttribute("enctype", "multipart/form-data");
14
- element.setAttribute("novalidate", "true");
15
- element.setAttribute("action", useSystemUri("full"));
16
- element.setAttribute("style", "display: none;");
17
- const csrf = document.createElement("input");
18
- csrf.setAttribute("type", "hidden");
19
- csrf.setAttribute("name", "anticsrf");
20
- csrf.setAttribute("value", data("csrf-token"));
21
- element.appendChild(csrf);
22
- document.body.appendChild(element);
23
- }
24
- this.element = element;
25
- this.options = { ...options };
26
- }
27
- initComponent(store = "form", custom = {}) {
28
- return loadAlpine((Alpine) => {
29
- Alpine.store(store, this.useState(custom));
30
- });
31
- }
32
- useState(custom = {}) {
33
- const state = {};
34
- Object.getOwnPropertyNames(Object.getPrototypeOf(this)).map((item) => {
35
- return state[item] = this[item].bind(this);
36
- });
37
- return Object.assign(
38
- state,
39
- custom
40
- );
41
- }
42
- getElement() {
43
- return this.element;
44
- }
45
- submit(url, data2, method, customMethod) {
46
- const form = this.element;
47
- if (customMethod) {
48
- let methodInput = form.querySelector('input[name="_method"]');
49
- if (!methodInput) {
50
- methodInput = document.createElement("input");
51
- methodInput.setAttribute("name", "_method");
52
- methodInput.setAttribute("type", "hidden");
53
- methodInput.value = customMethod;
54
- form.appendChild(methodInput);
55
- } else {
56
- methodInput.value = customMethod;
57
- }
58
- }
59
- if (data2) {
60
- const flatted = UnicornFormElement.flattenObject(data2);
61
- for (const key in flatted) {
62
- const value = flatted[key];
63
- const fieldName = UnicornFormElement.buildFieldName(key);
64
- this.injectInput(fieldName, value);
65
- }
66
- }
67
- if (url) {
68
- form.setAttribute("action", url);
69
- }
70
- if (method) {
71
- form.setAttribute("method", method);
72
- }
73
- form.requestSubmit();
74
- return true;
75
- }
76
- injectInput(name, value) {
77
- let input = this.element.querySelector(`input[name="${name}"]`);
78
- if (!input) {
79
- input = document.createElement("input");
80
- input.setAttribute("name", name);
81
- input.setAttribute("type", "hidden");
82
- input.setAttribute("data-role", "temp-input");
83
- this.element.appendChild(input);
84
- }
85
- input.value = value;
86
- return input;
87
- }
88
- /**
89
- * Make a GET request.
90
- */
91
- get(url, data2, customMethod) {
92
- return this.submit(url, data2, "GET", customMethod);
93
- }
94
- /**
95
- * Post form.
96
- */
97
- post(url, data2, customMethod) {
98
- customMethod = customMethod || "POST";
99
- return this.submit(url, data2, "POST", customMethod);
100
- }
101
- /**
102
- * Make a PUT request.
103
- */
104
- put(url, data2) {
105
- return this.post(url, data2, "PUT");
106
- }
107
- /**
108
- * Make a PATCH request.
109
- */
110
- patch(url, data2) {
111
- return this.post(url, data2, "PATCH");
112
- }
113
- /**
114
- * Make a DELETE request.
115
- */
116
- delete(url, data2) {
117
- return this.post(url, data2, "DELETE");
118
- }
119
- destroy() {
120
- if (this.element) {
121
- this.element.remove();
122
- this.element = void 0;
123
- }
124
- }
125
- /**
126
- * @see https://stackoverflow.com/a/53739792
127
- *
128
- * @param {Object} ob
129
- * @returns {Object}
130
- */
131
- static flattenObject(ob) {
132
- const toReturn = {};
133
- for (let i in ob) {
134
- if (!ob.hasOwnProperty(i)) {
135
- continue;
136
- }
137
- if (typeof ob[i] === "object" && ob[i] != null) {
138
- const flatObject = this.flattenObject(ob[i]);
139
- for (let x in flatObject) {
140
- if (!flatObject.hasOwnProperty(x)) {
141
- continue;
142
- }
143
- toReturn[i + "/" + x] = flatObject[x];
144
- }
145
- } else {
146
- toReturn[i] = ob[i];
147
- }
148
- }
149
- return toReturn;
150
- }
151
- static buildFieldName(field) {
152
- const names = field.split("/");
153
- const first = names.shift();
154
- return first + names.map((name) => `[${name}]`).join("");
155
- }
156
- }
157
- export {
158
- UnicornFormElement
1
+ import { t as data } from "./data.js";
2
+ import { s as loadAlpine } from "./ui.js";
3
+ import { useSystemUri } from "../unicorn.js";
4
+ //#region src/module/form.ts
5
+ var UnicornFormElement = class UnicornFormElement {
6
+ element;
7
+ options;
8
+ constructor(selector, element, options = {}) {
9
+ if (!element) {
10
+ element = document.createElement("form");
11
+ if (typeof selector === "string" && selector.startsWith("#")) {
12
+ element.setAttribute("id", selector.substring(1));
13
+ element.setAttribute("name", selector.substring(1));
14
+ }
15
+ element.setAttribute("method", "post");
16
+ element.setAttribute("enctype", "multipart/form-data");
17
+ element.setAttribute("novalidate", "true");
18
+ element.setAttribute("action", useSystemUri("full"));
19
+ element.setAttribute("style", "display: none;");
20
+ const csrf = document.createElement("input");
21
+ csrf.setAttribute("type", "hidden");
22
+ csrf.setAttribute("name", "anticsrf");
23
+ csrf.setAttribute("value", data("csrf-token"));
24
+ element.appendChild(csrf);
25
+ document.body.appendChild(element);
26
+ }
27
+ this.element = element;
28
+ this.options = { ...options };
29
+ }
30
+ initComponent(store = "form", custom = {}) {
31
+ return loadAlpine((Alpine) => {
32
+ Alpine.store(store, this.useState(custom));
33
+ });
34
+ }
35
+ useState(custom = {}) {
36
+ const state = {};
37
+ Object.getOwnPropertyNames(Object.getPrototypeOf(this)).map((item) => {
38
+ return state[item] = this[item].bind(this);
39
+ });
40
+ return Object.assign(state, custom);
41
+ }
42
+ getElement() {
43
+ return this.element;
44
+ }
45
+ submit(url, data, method, customMethod) {
46
+ const form = this.element;
47
+ if (customMethod) {
48
+ let methodInput = form.querySelector("input[name=\"_method\"]");
49
+ if (!methodInput) {
50
+ methodInput = document.createElement("input");
51
+ methodInput.setAttribute("name", "_method");
52
+ methodInput.setAttribute("type", "hidden");
53
+ methodInput.value = customMethod;
54
+ form.appendChild(methodInput);
55
+ } else methodInput.value = customMethod;
56
+ }
57
+ if (data) {
58
+ const flatted = UnicornFormElement.flattenObject(data);
59
+ for (const key in flatted) {
60
+ const value = flatted[key];
61
+ const fieldName = UnicornFormElement.buildFieldName(key);
62
+ this.injectInput(fieldName, value);
63
+ }
64
+ }
65
+ if (url) form.setAttribute("action", url);
66
+ if (method) form.setAttribute("method", method);
67
+ form.requestSubmit();
68
+ return true;
69
+ }
70
+ injectInput(name, value) {
71
+ let input = this.element.querySelector(`input[name="${name}"]`);
72
+ if (!input) {
73
+ input = document.createElement("input");
74
+ input.setAttribute("name", name);
75
+ input.setAttribute("type", "hidden");
76
+ input.setAttribute("data-role", "temp-input");
77
+ this.element.appendChild(input);
78
+ }
79
+ input.value = value;
80
+ return input;
81
+ }
82
+ /**
83
+ * Make a GET request.
84
+ */
85
+ get(url, data, customMethod) {
86
+ return this.submit(url, data, "GET", customMethod);
87
+ }
88
+ /**
89
+ * Post form.
90
+ */
91
+ post(url, data, customMethod) {
92
+ customMethod = customMethod || "POST";
93
+ return this.submit(url, data, "POST", customMethod);
94
+ }
95
+ /**
96
+ * Make a PUT request.
97
+ */
98
+ put(url, data) {
99
+ return this.post(url, data, "PUT");
100
+ }
101
+ /**
102
+ * Make a PATCH request.
103
+ */
104
+ patch(url, data) {
105
+ return this.post(url, data, "PATCH");
106
+ }
107
+ /**
108
+ * Make a DELETE request.
109
+ */
110
+ delete(url, data) {
111
+ return this.post(url, data, "DELETE");
112
+ }
113
+ destroy() {
114
+ if (this.element) {
115
+ this.element.remove();
116
+ this.element = void 0;
117
+ }
118
+ }
119
+ /**
120
+ * @see https://stackoverflow.com/a/53739792
121
+ *
122
+ * @param {Object} ob
123
+ * @returns {Object}
124
+ */
125
+ static flattenObject(ob) {
126
+ const toReturn = {};
127
+ for (let i in ob) {
128
+ if (!ob.hasOwnProperty(i)) continue;
129
+ if (typeof ob[i] === "object" && ob[i] != null) {
130
+ const flatObject = this.flattenObject(ob[i]);
131
+ for (let x in flatObject) {
132
+ if (!flatObject.hasOwnProperty(x)) continue;
133
+ toReturn[i + "/" + x] = flatObject[x];
134
+ }
135
+ } else toReturn[i] = ob[i];
136
+ }
137
+ return toReturn;
138
+ }
139
+ static buildFieldName(field) {
140
+ const names = field.split("/");
141
+ return names.shift() + names.map((name) => `[${name}]`).join("");
142
+ }
159
143
  };
160
- //# sourceMappingURL=form.js.map
144
+ //#endregion
145
+ export { UnicornFormElement };
146
+
147
+ //# sourceMappingURL=form.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sources":["../../src/module/form.ts"],"sourcesContent":["import { data } from '../data';\nimport { loadAlpine, useSystemUri } from '../service';\nimport type { Nullable } from '../types';\n\nexport class UnicornFormElement {\n element: HTMLFormElement | undefined;\n options: Record<string, any>;\n\n constructor(\n selector?: string | Element,\n element?: HTMLFormElement,\n options: Record<string, any> = {},\n ) {\n // If form not found, create one\n if (!element) {\n element = document.createElement('form');\n\n if (typeof selector === 'string' && selector.startsWith('#')) {\n element.setAttribute('id', selector.substring(1));\n element.setAttribute('name', selector.substring(1));\n }\n\n element.setAttribute('method', 'post');\n element.setAttribute('enctype', 'multipart/form-data');\n element.setAttribute('novalidate', 'true');\n element.setAttribute('action', useSystemUri('full'));\n element.setAttribute('style', 'display: none;');\n\n const csrf = document.createElement('input');\n csrf.setAttribute('type', 'hidden');\n csrf.setAttribute('name', 'anticsrf');\n csrf.setAttribute('value', data('csrf-token'));\n\n element.appendChild(csrf);\n document.body.appendChild(element);\n }\n\n this.element = element;\n this.options = { ...options };\n }\n\n initComponent(store = 'form', custom = {}) {\n return loadAlpine((Alpine) => {\n Alpine.store(store, this.useState(custom));\n });\n }\n\n useState(custom = {}) {\n const state: Record<string, any> = {};\n Object.getOwnPropertyNames(Object.getPrototypeOf(this))\n .map(item => {\n // @ts-ignore\n return state[item] = this[item].bind(this);\n });\n\n return Object.assign(\n state,\n custom\n );\n }\n\n getElement() {\n return this.element;\n }\n\n submit(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n method?: Nullable<string>,\n customMethod?: Nullable<string>,\n ): boolean {\n const form = this.element!;\n\n if (customMethod) {\n let methodInput = form.querySelector<HTMLInputElement>('input[name=\"_method\"]');\n\n if (!methodInput) {\n methodInput = document.createElement('input');\n methodInput.setAttribute('name', '_method');\n methodInput.setAttribute('type', 'hidden');\n methodInput.value = customMethod;\n\n form.appendChild(methodInput);\n } else {\n methodInput.value = customMethod;\n }\n }\n\n // Set data into form.\n if (data) {\n const flatted = UnicornFormElement.flattenObject(data);\n\n for (const key in flatted) {\n const value = flatted[key];\n\n const fieldName = UnicornFormElement.buildFieldName(key);\n this.injectInput(fieldName, value);\n }\n }\n\n if (url) {\n form.setAttribute('action', url);\n }\n\n if (method) {\n form.setAttribute('method', method);\n }\n\n // Use requestSubmit() to fire submit event.\n form.requestSubmit();\n\n return true;\n }\n\n injectInput(name: string, value: any) {\n let input = this.element!.querySelector<HTMLInputElement>(`input[name=\"${name}\"]`);\n\n if (!input) {\n input = document.createElement('input');\n input.setAttribute('name', name);\n input.setAttribute('type', 'hidden');\n input.setAttribute('data-role', 'temp-input');\n\n this.element!.appendChild(input);\n }\n\n input.value = value;\n return input;\n }\n\n /**\n * Make a GET request.\n */\n get(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n customMethod?: Nullable<string>,\n ): boolean {\n return this.submit(url, data, 'GET', customMethod);\n }\n\n /**\n * Post form.\n */\n post(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n customMethod?: Nullable<string>,\n ) {\n customMethod = customMethod || 'POST';\n\n return this.submit(url, data, 'POST', customMethod);\n }\n\n /**\n * Make a PUT request.\n */\n put(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'PUT');\n }\n\n /**\n * Make a PATCH request.\n */\n patch(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'PATCH');\n }\n\n /**\n * Make a DELETE request.\n */\n delete(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'DELETE');\n }\n\n destroy() {\n if (this.element) {\n this.element.remove();\n this.element = undefined;\n }\n }\n\n /**\n * @see https://stackoverflow.com/a/53739792\n *\n * @param {Object} ob\n * @returns {Object}\n */\n static flattenObject(ob: Record<string, any>): Record<string, any> {\n const toReturn: Record<string, any> = {};\n\n for (let i in ob) {\n if (!ob.hasOwnProperty(i)) {\n continue;\n }\n\n if ((typeof ob[i]) === 'object' && ob[i] != null) {\n const flatObject = this.flattenObject(ob[i]);\n\n for (let x in flatObject) {\n if (!flatObject.hasOwnProperty(x)) {\n continue;\n }\n\n toReturn[i + '/' + x] = flatObject[x];\n }\n } else {\n toReturn[i] = ob[i];\n }\n }\n return toReturn;\n }\n\n static buildFieldName(field: string) {\n const names = field.split('/');\n\n const first = names.shift();\n\n return first + names.map(name => `[${name}]`).join('');\n }\n}\n"],"names":["data"],"mappings":"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"}
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../src/module/form.ts"],"sourcesContent":["import { data } from '../data';\nimport { loadAlpine, useSystemUri } from '../service';\nimport type { Nullable } from '../types';\n\nexport class UnicornFormElement {\n element: HTMLFormElement | undefined;\n options: Record<string, any>;\n\n constructor(\n selector?: string | Element,\n element?: HTMLFormElement,\n options: Record<string, any> = {},\n ) {\n // If form not found, create one\n if (!element) {\n element = document.createElement('form');\n\n if (typeof selector === 'string' && selector.startsWith('#')) {\n element.setAttribute('id', selector.substring(1));\n element.setAttribute('name', selector.substring(1));\n }\n\n element.setAttribute('method', 'post');\n element.setAttribute('enctype', 'multipart/form-data');\n element.setAttribute('novalidate', 'true');\n element.setAttribute('action', useSystemUri('full'));\n element.setAttribute('style', 'display: none;');\n\n const csrf = document.createElement('input');\n csrf.setAttribute('type', 'hidden');\n csrf.setAttribute('name', 'anticsrf');\n csrf.setAttribute('value', data('csrf-token'));\n\n element.appendChild(csrf);\n document.body.appendChild(element);\n }\n\n this.element = element;\n this.options = { ...options };\n }\n\n initComponent(store = 'form', custom = {}) {\n return loadAlpine((Alpine) => {\n Alpine.store(store, this.useState(custom));\n });\n }\n\n useState(custom = {}) {\n const state: Record<string, any> = {};\n Object.getOwnPropertyNames(Object.getPrototypeOf(this))\n .map(item => {\n // @ts-ignore\n return state[item] = this[item].bind(this);\n });\n\n return Object.assign(\n state,\n custom\n );\n }\n\n getElement() {\n return this.element;\n }\n\n submit(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n method?: Nullable<string>,\n customMethod?: Nullable<string>,\n ): boolean {\n const form = this.element!;\n\n if (customMethod) {\n let methodInput = form.querySelector<HTMLInputElement>('input[name=\"_method\"]');\n\n if (!methodInput) {\n methodInput = document.createElement('input');\n methodInput.setAttribute('name', '_method');\n methodInput.setAttribute('type', 'hidden');\n methodInput.value = customMethod;\n\n form.appendChild(methodInput);\n } else {\n methodInput.value = customMethod;\n }\n }\n\n // Set data into form.\n if (data) {\n const flatted = UnicornFormElement.flattenObject(data);\n\n for (const key in flatted) {\n const value = flatted[key];\n\n const fieldName = UnicornFormElement.buildFieldName(key);\n this.injectInput(fieldName, value);\n }\n }\n\n if (url) {\n form.setAttribute('action', url);\n }\n\n if (method) {\n form.setAttribute('method', method);\n }\n\n // Use requestSubmit() to fire submit event.\n form.requestSubmit();\n\n return true;\n }\n\n injectInput(name: string, value: any) {\n let input = this.element!.querySelector<HTMLInputElement>(`input[name=\"${name}\"]`);\n\n if (!input) {\n input = document.createElement('input');\n input.setAttribute('name', name);\n input.setAttribute('type', 'hidden');\n input.setAttribute('data-role', 'temp-input');\n\n this.element!.appendChild(input);\n }\n\n input.value = value;\n return input;\n }\n\n /**\n * Make a GET request.\n */\n get(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n customMethod?: Nullable<string>,\n ): boolean {\n return this.submit(url, data, 'GET', customMethod);\n }\n\n /**\n * Post form.\n */\n post(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n customMethod?: Nullable<string>,\n ) {\n customMethod = customMethod || 'POST';\n\n return this.submit(url, data, 'POST', customMethod);\n }\n\n /**\n * Make a PUT request.\n */\n put(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'PUT');\n }\n\n /**\n * Make a PATCH request.\n */\n patch(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'PATCH');\n }\n\n /**\n * Make a DELETE request.\n */\n delete(\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>,\n ) {\n return this.post(url, data, 'DELETE');\n }\n\n destroy() {\n if (this.element) {\n this.element.remove();\n this.element = undefined;\n }\n }\n\n /**\n * @see https://stackoverflow.com/a/53739792\n *\n * @param {Object} ob\n * @returns {Object}\n */\n static flattenObject(ob: Record<string, any>): Record<string, any> {\n const toReturn: Record<string, any> = {};\n\n for (let i in ob) {\n if (!ob.hasOwnProperty(i)) {\n continue;\n }\n\n if ((typeof ob[i]) === 'object' && ob[i] != null) {\n const flatObject = this.flattenObject(ob[i]);\n\n for (let x in flatObject) {\n if (!flatObject.hasOwnProperty(x)) {\n continue;\n }\n\n toReturn[i + '/' + x] = flatObject[x];\n }\n } else {\n toReturn[i] = ob[i];\n }\n }\n return toReturn;\n }\n\n static buildFieldName(field: string) {\n const names = field.split('/');\n\n const first = names.shift();\n\n return first + names.map(name => `[${name}]`).join('');\n }\n}\n"],"mappings":"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"}