@windwalker-io/unicorn-next 0.1.5 → 0.1.6

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 (128) hide show
  1. package/.editorconfig +18 -18
  2. package/.gulp.json +7 -7
  3. package/bin/release.mjs +47 -47
  4. package/dist/chunks/button-radio.js.map +1 -1
  5. package/dist/chunks/checkboxes-multi-select.js.map +1 -1
  6. package/dist/chunks/field-cascade-select.js.map +1 -1
  7. package/dist/chunks/field-file-drag.js.map +1 -1
  8. package/dist/chunks/field-flatpickr.js.map +1 -1
  9. package/dist/chunks/field-modal-select.js.map +1 -1
  10. package/dist/chunks/field-modal-tree.js +2 -2
  11. package/dist/chunks/field-modal-tree.js.map +1 -1
  12. package/dist/chunks/field-multi-uploader.js.map +1 -1
  13. package/dist/chunks/field-repeatable.js.map +1 -1
  14. package/dist/chunks/field-single-image-drag.js.map +1 -1
  15. package/dist/chunks/form.js.map +1 -1
  16. package/dist/chunks/grid.js.map +1 -1
  17. package/dist/chunks/http-client.js.map +1 -1
  18. package/dist/chunks/iframe-modal.js.map +1 -1
  19. package/dist/chunks/keep-tab.js.map +1 -1
  20. package/dist/chunks/legacy.js.map +1 -1
  21. package/dist/chunks/list-dependent.js.map +1 -1
  22. package/dist/chunks/s3-multipart-uploader.js.map +1 -1
  23. package/dist/chunks/s3-uploader.js.map +1 -1
  24. package/dist/chunks/show-on.js.map +1 -1
  25. package/dist/chunks/tinymce.js +1 -1
  26. package/dist/chunks/tinymce.js.map +1 -1
  27. package/dist/chunks/ui-bootstrap5.js.map +1 -1
  28. package/dist/chunks/unicorn.js +20 -14
  29. package/dist/chunks/unicorn.js.map +1 -1
  30. package/dist/chunks/validation.js +1 -1
  31. package/dist/chunks/validation.js.map +1 -1
  32. package/dist/index.d.ts +16 -14
  33. package/dist/unicorn.js +10 -8
  34. package/fusionfile.mjs +155 -155
  35. package/package.json +103 -103
  36. package/scss/bootstrap/multi-level-menu.scss +121 -121
  37. package/scss/editor.scss +116 -116
  38. package/scss/field/file-drag.scss +102 -102
  39. package/scss/field/single-image-drag.scss +88 -88
  40. package/scss/field/vue-drag-uploader.scss +160 -160
  41. package/scss/switcher.scss +156 -156
  42. package/src/app.ts +128 -128
  43. package/src/bootstrap/button-radio.ts +208 -208
  44. package/src/bootstrap/keep-tab.ts +155 -155
  45. package/src/composable/index.ts +22 -21
  46. package/src/composable/useCheckboxesMultiSelect.ts +22 -22
  47. package/src/composable/useFieldCascadeSelect.ts +9 -9
  48. package/src/composable/useFieldFileDrag.ts +9 -9
  49. package/src/composable/useFieldFlatpickr.ts +3 -3
  50. package/src/composable/useFieldModalSelect.ts +6 -6
  51. package/src/composable/useFieldModalTree.ts +3 -3
  52. package/src/composable/useFieldMultiUploader.ts +9 -9
  53. package/src/composable/useFieldRepeatable.ts +9 -9
  54. package/src/composable/useFieldSingleImageDrag.ts +9 -9
  55. package/src/composable/useForm.ts +43 -43
  56. package/src/composable/useGrid.ts +57 -57
  57. package/src/composable/useHttp.ts +9 -9
  58. package/src/composable/useIframeModal.ts +10 -10
  59. package/src/composable/useListDependent.ts +26 -26
  60. package/src/composable/useQueue.ts +13 -13
  61. package/src/composable/useS3Uploader.ts +32 -32
  62. package/src/composable/useShowOn.ts +9 -9
  63. package/src/composable/useStack.ts +13 -13
  64. package/src/composable/useTinymce.ts +29 -29
  65. package/src/composable/useTomSelect.ts +72 -72
  66. package/src/composable/useUIBootstrap5.ts +48 -48
  67. package/src/composable/useUniDirective.ts +32 -32
  68. package/src/composable/useValidation.ts +50 -50
  69. package/src/data.ts +34 -34
  70. package/src/events.ts +82 -82
  71. package/src/legacy/legacy.ts +190 -190
  72. package/src/legacy/loader.ts +125 -125
  73. package/src/module/checkboxes-multi-select.ts +54 -54
  74. package/src/module/field-cascade-select.ts +292 -292
  75. package/src/module/field-file-drag.ts +295 -295
  76. package/src/module/field-flatpickr.ts +130 -130
  77. package/src/module/field-modal-select.ts +179 -179
  78. package/src/module/field-modal-tree.ts +31 -31
  79. package/src/module/field-multi-uploader.ts +368 -368
  80. package/src/module/field-repeatable.ts +202 -202
  81. package/src/module/field-single-image-drag.ts +475 -475
  82. package/src/module/form.ts +223 -223
  83. package/src/module/grid.ts +465 -465
  84. package/src/module/http-client.ts +248 -248
  85. package/src/module/iframe-modal.ts +170 -170
  86. package/src/module/list-dependent.ts +321 -321
  87. package/src/module/s3-multipart-uploader.ts +300 -300
  88. package/src/module/s3-uploader.ts +234 -234
  89. package/src/module/show-on.ts +175 -175
  90. package/src/module/tinymce.ts +276 -276
  91. package/src/module/ui-bootstrap5.ts +116 -116
  92. package/src/module/validation.ts +1046 -1046
  93. package/src/plugin/index.ts +1 -1
  94. package/src/plugin/php-adapter.ts +72 -72
  95. package/src/polyfill/form-request-submit.ts +31 -31
  96. package/src/polyfill/index.ts +9 -9
  97. package/src/service/animate.ts +58 -58
  98. package/src/service/crypto.ts +27 -27
  99. package/src/service/dom-watcher.ts +62 -62
  100. package/src/service/dom.ts +265 -265
  101. package/src/service/helper.ts +48 -48
  102. package/src/service/index.ts +10 -10
  103. package/src/service/lang.ts +122 -122
  104. package/src/service/loader.ts +152 -152
  105. package/src/service/router.ts +118 -118
  106. package/src/service/ui.ts +525 -525
  107. package/src/service/uri.ts +106 -106
  108. package/src/types/base.ts +9 -9
  109. package/src/types/index.ts +4 -4
  110. package/src/types/modal-tree.ts +12 -12
  111. package/src/types/plugin.ts +6 -6
  112. package/src/types/shims.d.ts +18 -18
  113. package/src/types/ui.ts +6 -6
  114. package/src/unicorn.ts +79 -79
  115. package/src/utilities/arr.ts +25 -25
  116. package/src/utilities/base.ts +9 -9
  117. package/src/utilities/data.ts +48 -48
  118. package/src/utilities/index.ts +5 -5
  119. package/src/utilities/tree.ts +20 -20
  120. package/src/vue/components/ModalTree/ModalTreeApp.vue +175 -175
  121. package/src/vue/components/ModalTree/TreeItem.vue +262 -262
  122. package/src/vue/components/ModalTree/TreeModal.vue +225 -225
  123. package/tests/test.js +4 -4
  124. package/tsconfig.js.json +25 -25
  125. package/tsconfig.json +17 -17
  126. package/vite.assets.config.ts +61 -61
  127. package/vite.config.test.ts +36 -36
  128. package/vite.config.ts +112 -112
@@ -1 +1 @@
1
- {"version":3,"file":"field-multi-uploader.js","sources":["../../src/module/field-multi-uploader.ts"],"sourcesContent":["import { Modal } from 'bootstrap';\r\nimport type { Options } from 'sortablejs';\r\nimport {\r\n type ComponentPublicInstance,\r\n computed,\r\n createApp,\r\n defineComponent,\r\n getCurrentInstance,\r\n nextTick,\r\n onMounted,\r\n PropType,\r\n ref,\r\n useTemplateRef\r\n} from 'vue';\r\nimport { VueDraggable } from 'vue-draggable-plus';\r\nimport {\r\n createItem,\r\n ItemCard,\r\n ItemCardPlaceholder,\r\n MultiUploader,\r\n MultiUploaderComposableInstance,\r\n MultiUploaderOptions,\r\n UploaderItem\r\n} from 'vue-multi-uploader';\r\nimport css from 'vue-multi-uploader/src/vue-multi-uploader.scss?inline';\r\nimport { useStack } from '../composable';\r\nimport { data } from '../data';\r\nimport { forceArray, injectCssToDocument } from '../service';\r\nimport { mergeDeep } from '../utilities';\r\n\r\nexport type UniMultiUploaderOptions = {\r\n value?: any[];\r\n uploadUrl: string;\r\n maxFiles?: number;\r\n maxConcurrent?: number;\r\n thumbSize?: number;\r\n accept?: string;\r\n readonly: boolean;\r\n disabled: boolean;\r\n fieldName?: string;\r\n fieldFullName?: string;\r\n tmplSelector: string;\r\n canReplace: false;\r\n openFileHandler?: (item: UploaderItem) => void;\r\n}\r\n\r\nconst defaultOptions = {\r\n readonly: false,\r\n disabled: false,\r\n sortable: false,\r\n thumbSize: 150,\r\n maxConcurrent: 5,\r\n canReplace: false,\r\n tmplSelector: '#multi-uploader-field-tmpl',\r\n};\r\n\r\nexport class MultiUploaderElement extends HTMLElement {\r\n static is = 'uni-multi-uploader';\r\n\r\n modalElement!: HTMLDivElement;\r\n vm!: ComponentPublicInstance;\r\n\r\n async connectedCallback() {\r\n let options: Partial<UniMultiUploaderOptions> = JSON.parse(\r\n this.getAttribute('options') || '{}'\r\n );\r\n\r\n const resolvedOptions: UniMultiUploaderOptions = mergeDeep({}, defaultOptions, options);\r\n\r\n // Make some default options since PHP will send NULL\r\n resolvedOptions.thumbSize ??= 150;\r\n\r\n this.modalElement = this.querySelector<HTMLDivElement>('.modal')!;\r\n\r\n const tmplSelector = resolvedOptions.tmplSelector;\r\n\r\n const app = createApp(\r\n createAppInstance(resolvedOptions, document.querySelector(tmplSelector)!.innerHTML, this)\r\n );\r\n\r\n this.vm = app.mount(this);\r\n }\r\n}\r\n\r\nasync function init() {\r\n injectCssToDocument(css);\r\n customElements.define(MultiUploaderElement.is, MultiUploaderElement);\r\n}\r\nexport const ready = init();\r\n\r\nexport interface MultiUploaderModule {\r\n MultiUploaderElement: typeof MultiUploaderElement;\r\n ready: typeof ready;\r\n}\r\n\r\nfunction createAppInstance(opt: UniMultiUploaderOptions, tmpl: string, el: MultiUploaderElement) {\r\n return defineComponent({\r\n name: 'MultiUploaderFieldApp',\r\n template: tmpl,\r\n components: {\r\n VueDraggable,\r\n MultiUploader,\r\n ItemCard,\r\n ItemCardPlaceholder,\r\n },\r\n props: {\r\n stackName: String as PropType<string>,\r\n },\r\n setup(props, { expose }) {\r\n const options = ref<UniMultiUploaderOptions>(opt);\r\n const current = ref<UploaderItem>();\r\n const currentIndex = ref<number>();\r\n const loading = ref(false);\r\n const dragarea = ref<HTMLDivElement>();\r\n const modal = ref<HTMLDivElement>();\r\n const app = getCurrentInstance();\r\n const uploader = useTemplateRef<typeof MultiUploader>('uploader');\r\n const canModify = computed(() => !options.value.disabled && !options.value.readonly);\r\n const instance = ref<MultiUploaderComposableInstance>();\r\n\r\n onMounted(() => {\r\n instance.value = uploader.value!.instance;\r\n\r\n domEmit('multi-uploader:mounted', { app, uploader });\r\n });\r\n\r\n const items = ref<UploaderItem[]>([]);\r\n\r\n for (let item of forceArray(options.value.value)) {\r\n if (typeof item === 'string') {\r\n item = {\r\n url: item\r\n };\r\n }\r\n\r\n const uploadItem = createItem({\r\n url: item.url || '',\r\n thumbUrl: item.thumbUrl || item.thumb_url || item.url || '',\r\n data: item\r\n });\r\n\r\n items.value.push(uploadItem);\r\n }\r\n\r\n const uploadUrl = options.value.uploadUrl;\r\n const value = items.value;\r\n const uploaderOptions = ref<MultiUploaderOptions>({\r\n maxFiles: () => options.value.maxFiles,\r\n readonly: () => options.value.readonly,\r\n disabled: () => options.value.disabled,\r\n accept: () => options.value.accept,\r\n maxConcurrent: () => options.value.maxConcurrent,\r\n prepareXhr(xhr) {\r\n xhr.setRequestHeader(\r\n 'X-CSRF-TOKEN',\r\n data('csrf-token')\r\n );\r\n },\r\n onItemUploadSuccess(item, xhr) {\r\n const res = JSON.parse(xhr.responseText);\r\n item.url = res.data.url;\r\n item.thumbUrl = res.data.thumbUrl || res.data.thumb_url || res.data.url;\r\n item.data = res.data;\r\n item.data.title ??= item.url.split('/').pop()?.split('?').shift() || '';\r\n }\r\n });\r\n const draggableOptions: Options = {\r\n draggable: '.c-drag-item',\r\n animation: 300,\r\n disabled: !canModify.value,\r\n };\r\n\r\n function openFile(item: UploaderItem) {\r\n if (options.value.openFileHandler) {\r\n options.value.openFileHandler(item);\r\n } else {\r\n window.open(item.download_url || item.url);\r\n }\r\n }\r\n\r\n async function itemClick(item: UploaderItem, i: number, event: MouseEvent) {\r\n current.value = item;\r\n currentIndex.value = i;\r\n\r\n domEmit('item-click', { item, i });\r\n\r\n nextTick().then(() => {\r\n Modal.getOrCreateInstance(modal.value!).show();\r\n });\r\n // this.$options.metaModal.modal('show');\r\n }\r\n\r\n function metaSave() {\r\n current.value = undefined;\r\n currentIndex.value = undefined;\r\n\r\n // nextTick().then(() => {\r\n // new bootstrap.Modal(modal.value).hide();\r\n // });\r\n // this.$options.metaModal.modal('hide');\r\n }\r\n\r\n function isImage(url: string) {\r\n const ext = url.split('.').pop()!.split('?').shift() || '';\r\n const allow = ['png', 'jpeg', 'jpg', 'gif', 'bmp', 'webp'];\r\n\r\n return allow.indexOf(ext.toLowerCase()) !== -1;\r\n }\r\n\r\n function dragover(e: DragEvent) {\r\n if (!options.value.canReplace) {\r\n return;\r\n }\r\n\r\n dragarea.value!.style.opacity = '0.75';\r\n }\r\n\r\n function dragleave(e: DragEvent) {\r\n if (!options.value.canReplace) {\r\n return;\r\n }\r\n\r\n dragarea.value!.style.opacity = '1';\r\n }\r\n\r\n function drop(event: DragEvent) {\r\n if (!options.value.canReplace) {\r\n return;\r\n }\r\n\r\n dragarea.value!.style.opacity = '1';\r\n const item = current.value;\r\n const file = event.dataTransfer?.files[0] || null;\r\n\r\n if (!file) {\r\n return;\r\n }\r\n\r\n instance.value!.checkFile(file);\r\n\r\n if (instance.value!.isReadonly) {\r\n return;\r\n }\r\n\r\n item!.file = file;\r\n\r\n loading.value = true;\r\n\r\n try {\r\n instance.value!.uploadFile(item!);\r\n } finally {\r\n loading.value = false;\r\n }\r\n }\r\n\r\n function uploading() {\r\n useStack(props.stackName).push(true);\r\n\r\n domEmit('uploading');\r\n }\r\n\r\n function uploaded() {\r\n useStack(props.stackName).pop();\r\n\r\n domEmit('uploaded');\r\n }\r\n\r\n function onChange(item: UploaderItem) {\r\n domEmit('change', item);\r\n }\r\n\r\n function domEmit(event: string, detail?: any) {\r\n el.dispatchEvent(new CustomEvent(event, { detail }));\r\n }\r\n\r\n const foo = ref<string>();\r\n\r\n foo.value = 'Bar';\r\n\r\n const icons = ref<Record<string, string>>({\r\n default: 'fas fa-file',\r\n pdf: 'fas fa-file-pdf text-danger',\r\n xls: 'fas fa-file-excel text-success',\r\n xlsx: 'fas fa-file-excel text-success',\r\n doc: 'fas fa-file-word text-primary',\r\n docx: 'fas fa-file-word text-primary',\r\n ppt: 'fas fa-file-powerpoint text-warning',\r\n pptx: 'fas fa-file-powerpoint text-warning',\r\n zip: 'fas fa-file-archive text-dark',\r\n '7z': 'fas fa-file-archive text-dark',\r\n rar: 'fas fa-file-archive text-dark',\r\n mp4: 'fas fa-file-video text-dark',\r\n avi: 'fas fa-file-video text-dark',\r\n flv: 'fas fa-file-video text-dark',\r\n mov: 'fas fa-file-video text-dark',\r\n ogg: 'fas fa-file-video text-dark',\r\n webm: 'fas fa-file-video text-dark',\r\n mpg: 'fas fa-file-video text-dark',\r\n mp3: 'fas fa-file-audio text-dark',\r\n acc: 'fas fa-file-audio text-dark',\r\n wav: 'fas fa-file-audio text-dark',\r\n });\r\n\r\n function setIcons(newIcons: Record<string, string>, merge = true) {\r\n if (merge) {\r\n icons.value = { ...icons.value, ...newIcons };\r\n return;\r\n }\r\n\r\n icons.value = newIcons;\r\n }\r\n\r\n expose({\r\n uploader,\r\n instance,\r\n value,\r\n canModify,\r\n openFile,\r\n itemClick,\r\n isImage,\r\n setIcons,\r\n });\r\n\r\n function fileIcon(item: UploaderItem) {\r\n let path = item.file ? item.file.name : item.url;\r\n\r\n // strip query\r\n path = String(path).split('?')[0];\r\n\r\n // Get extension\r\n const ext = path.split('.').pop() || '';\r\n\r\n const def = 'default' in icons ? icons.default : 'fas fa-file';\r\n\r\n return icons[String(ext || 'default').toLowerCase() as keyof typeof icons] || def;\r\n }\r\n\r\n return {\r\n uploader,\r\n uploadUrl,\r\n value,\r\n uploaderOptions,\r\n draggableOptions,\r\n modal,\r\n dragarea,\r\n options,\r\n current,\r\n currentIndex,\r\n loading,\r\n instance,\r\n canModify,\r\n\r\n openFile,\r\n itemClick,\r\n metaSave,\r\n isImage,\r\n dragover,\r\n dragleave,\r\n drop,\r\n uploading,\r\n uploaded,\r\n onChange,\r\n domEmit,\r\n fileIcon,\r\n };\r\n }\r\n });\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"field-multi-uploader.js","sources":["../../src/module/field-multi-uploader.ts"],"sourcesContent":["import { Modal } from 'bootstrap';\nimport type { Options } from 'sortablejs';\nimport {\n type ComponentPublicInstance,\n computed,\n createApp,\n defineComponent,\n getCurrentInstance,\n nextTick,\n onMounted,\n PropType,\n ref,\n useTemplateRef\n} from 'vue';\nimport { VueDraggable } from 'vue-draggable-plus';\nimport {\n createItem,\n ItemCard,\n ItemCardPlaceholder,\n MultiUploader,\n MultiUploaderComposableInstance,\n MultiUploaderOptions,\n UploaderItem\n} from 'vue-multi-uploader';\nimport css from 'vue-multi-uploader/src/vue-multi-uploader.scss?inline';\nimport { useStack } from '../composable';\nimport { data } from '../data';\nimport { forceArray, injectCssToDocument } from '../service';\nimport { mergeDeep } from '../utilities';\n\nexport type UniMultiUploaderOptions = {\n value?: any[];\n uploadUrl: string;\n maxFiles?: number;\n maxConcurrent?: number;\n thumbSize?: number;\n accept?: string;\n readonly: boolean;\n disabled: boolean;\n fieldName?: string;\n fieldFullName?: string;\n tmplSelector: string;\n canReplace: false;\n openFileHandler?: (item: UploaderItem) => void;\n}\n\nconst defaultOptions = {\n readonly: false,\n disabled: false,\n sortable: false,\n thumbSize: 150,\n maxConcurrent: 5,\n canReplace: false,\n tmplSelector: '#multi-uploader-field-tmpl',\n};\n\nexport class MultiUploaderElement extends HTMLElement {\n static is = 'uni-multi-uploader';\n\n modalElement!: HTMLDivElement;\n vm!: ComponentPublicInstance;\n\n async connectedCallback() {\n let options: Partial<UniMultiUploaderOptions> = JSON.parse(\n this.getAttribute('options') || '{}'\n );\n\n const resolvedOptions: UniMultiUploaderOptions = mergeDeep({}, defaultOptions, options);\n\n // Make some default options since PHP will send NULL\n resolvedOptions.thumbSize ??= 150;\n\n this.modalElement = this.querySelector<HTMLDivElement>('.modal')!;\n\n const tmplSelector = resolvedOptions.tmplSelector;\n\n const app = createApp(\n createAppInstance(resolvedOptions, document.querySelector(tmplSelector)!.innerHTML, this)\n );\n\n this.vm = app.mount(this);\n }\n}\n\nasync function init() {\n injectCssToDocument(css);\n customElements.define(MultiUploaderElement.is, MultiUploaderElement);\n}\nexport const ready = init();\n\nexport interface MultiUploaderModule {\n MultiUploaderElement: typeof MultiUploaderElement;\n ready: typeof ready;\n}\n\nfunction createAppInstance(opt: UniMultiUploaderOptions, tmpl: string, el: MultiUploaderElement) {\n return defineComponent({\n name: 'MultiUploaderFieldApp',\n template: tmpl,\n components: {\n VueDraggable,\n MultiUploader,\n ItemCard,\n ItemCardPlaceholder,\n },\n props: {\n stackName: String as PropType<string>,\n },\n setup(props, { expose }) {\n const options = ref<UniMultiUploaderOptions>(opt);\n const current = ref<UploaderItem>();\n const currentIndex = ref<number>();\n const loading = ref(false);\n const dragarea = ref<HTMLDivElement>();\n const modal = ref<HTMLDivElement>();\n const app = getCurrentInstance();\n const uploader = useTemplateRef<typeof MultiUploader>('uploader');\n const canModify = computed(() => !options.value.disabled && !options.value.readonly);\n const instance = ref<MultiUploaderComposableInstance>();\n\n onMounted(() => {\n instance.value = uploader.value!.instance;\n\n domEmit('multi-uploader:mounted', { app, uploader });\n });\n\n const items = ref<UploaderItem[]>([]);\n\n for (let item of forceArray(options.value.value)) {\n if (typeof item === 'string') {\n item = {\n url: item\n };\n }\n\n const uploadItem = createItem({\n url: item.url || '',\n thumbUrl: item.thumbUrl || item.thumb_url || item.url || '',\n data: item\n });\n\n items.value.push(uploadItem);\n }\n\n const uploadUrl = options.value.uploadUrl;\n const value = items.value;\n const uploaderOptions = ref<MultiUploaderOptions>({\n maxFiles: () => options.value.maxFiles,\n readonly: () => options.value.readonly,\n disabled: () => options.value.disabled,\n accept: () => options.value.accept,\n maxConcurrent: () => options.value.maxConcurrent,\n prepareXhr(xhr) {\n xhr.setRequestHeader(\n 'X-CSRF-TOKEN',\n data('csrf-token')\n );\n },\n onItemUploadSuccess(item, xhr) {\n const res = JSON.parse(xhr.responseText);\n item.url = res.data.url;\n item.thumbUrl = res.data.thumbUrl || res.data.thumb_url || res.data.url;\n item.data = res.data;\n item.data.title ??= item.url.split('/').pop()?.split('?').shift() || '';\n }\n });\n const draggableOptions: Options = {\n draggable: '.c-drag-item',\n animation: 300,\n disabled: !canModify.value,\n };\n\n function openFile(item: UploaderItem) {\n if (options.value.openFileHandler) {\n options.value.openFileHandler(item);\n } else {\n window.open(item.download_url || item.url);\n }\n }\n\n async function itemClick(item: UploaderItem, i: number, event: MouseEvent) {\n current.value = item;\n currentIndex.value = i;\n\n domEmit('item-click', { item, i });\n\n nextTick().then(() => {\n Modal.getOrCreateInstance(modal.value!).show();\n });\n // this.$options.metaModal.modal('show');\n }\n\n function metaSave() {\n current.value = undefined;\n currentIndex.value = undefined;\n\n // nextTick().then(() => {\n // new bootstrap.Modal(modal.value).hide();\n // });\n // this.$options.metaModal.modal('hide');\n }\n\n function isImage(url: string) {\n const ext = url.split('.').pop()!.split('?').shift() || '';\n const allow = ['png', 'jpeg', 'jpg', 'gif', 'bmp', 'webp'];\n\n return allow.indexOf(ext.toLowerCase()) !== -1;\n }\n\n function dragover(e: DragEvent) {\n if (!options.value.canReplace) {\n return;\n }\n\n dragarea.value!.style.opacity = '0.75';\n }\n\n function dragleave(e: DragEvent) {\n if (!options.value.canReplace) {\n return;\n }\n\n dragarea.value!.style.opacity = '1';\n }\n\n function drop(event: DragEvent) {\n if (!options.value.canReplace) {\n return;\n }\n\n dragarea.value!.style.opacity = '1';\n const item = current.value;\n const file = event.dataTransfer?.files[0] || null;\n\n if (!file) {\n return;\n }\n\n instance.value!.checkFile(file);\n\n if (instance.value!.isReadonly) {\n return;\n }\n\n item!.file = file;\n\n loading.value = true;\n\n try {\n instance.value!.uploadFile(item!);\n } finally {\n loading.value = false;\n }\n }\n\n function uploading() {\n useStack(props.stackName).push(true);\n\n domEmit('uploading');\n }\n\n function uploaded() {\n useStack(props.stackName).pop();\n\n domEmit('uploaded');\n }\n\n function onChange(item: UploaderItem) {\n domEmit('change', item);\n }\n\n function domEmit(event: string, detail?: any) {\n el.dispatchEvent(new CustomEvent(event, { detail }));\n }\n\n const foo = ref<string>();\n\n foo.value = 'Bar';\n\n const icons = ref<Record<string, string>>({\n default: 'fas fa-file',\n pdf: 'fas fa-file-pdf text-danger',\n xls: 'fas fa-file-excel text-success',\n xlsx: 'fas fa-file-excel text-success',\n doc: 'fas fa-file-word text-primary',\n docx: 'fas fa-file-word text-primary',\n ppt: 'fas fa-file-powerpoint text-warning',\n pptx: 'fas fa-file-powerpoint text-warning',\n zip: 'fas fa-file-archive text-dark',\n '7z': 'fas fa-file-archive text-dark',\n rar: 'fas fa-file-archive text-dark',\n mp4: 'fas fa-file-video text-dark',\n avi: 'fas fa-file-video text-dark',\n flv: 'fas fa-file-video text-dark',\n mov: 'fas fa-file-video text-dark',\n ogg: 'fas fa-file-video text-dark',\n webm: 'fas fa-file-video text-dark',\n mpg: 'fas fa-file-video text-dark',\n mp3: 'fas fa-file-audio text-dark',\n acc: 'fas fa-file-audio text-dark',\n wav: 'fas fa-file-audio text-dark',\n });\n\n function setIcons(newIcons: Record<string, string>, merge = true) {\n if (merge) {\n icons.value = { ...icons.value, ...newIcons };\n return;\n }\n\n icons.value = newIcons;\n }\n\n expose({\n uploader,\n instance,\n value,\n canModify,\n openFile,\n itemClick,\n isImage,\n setIcons,\n });\n\n function fileIcon(item: UploaderItem) {\n let path = item.file ? item.file.name : item.url;\n\n // strip query\n path = String(path).split('?')[0];\n\n // Get extension\n const ext = path.split('.').pop() || '';\n\n const def = 'default' in icons ? icons.default : 'fas fa-file';\n\n return icons[String(ext || 'default').toLowerCase() as keyof typeof icons] || def;\n }\n\n return {\n uploader,\n uploadUrl,\n value,\n uploaderOptions,\n draggableOptions,\n modal,\n dragarea,\n options,\n current,\n currentIndex,\n loading,\n instance,\n canModify,\n\n openFile,\n itemClick,\n metaSave,\n isImage,\n dragover,\n dragleave,\n drop,\n uploading,\n uploaded,\n onChange,\n domEmit,\n fileIcon,\n };\n }\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-repeatable.js","sources":["../../src/module/field-repeatable.ts"],"sourcesContent":["import { cloneDeep } from 'lodash-es';\r\nimport { initAlpineComponent, prepareAlpineDefer, uid, useCssImport } from '../service';\r\nimport { mergeDeep } from '../utilities';\r\n\r\nexport interface RepeatableOptions {\r\n id?: string;\r\n fieldName?: string;\r\n sortable?: boolean;\r\n hasKey?: boolean;\r\n singleArray?: boolean;\r\n ensureFirstRow?: boolean;\r\n max?: number | null;\r\n}\r\n\r\nconst defaultOptions: RepeatableOptions = {\r\n id: '',\r\n fieldName: '',\r\n sortable: false,\r\n hasKey: false,\r\n singleArray: false,\r\n ensureFirstRow: false,\r\n max: null,\r\n};\r\n\r\nfunction prepareItem(item: any) {\r\n if (item.uid == null) {\r\n item.uid = uid();\r\n }\r\n return item;\r\n}\r\n\r\ntype RepeatableParams = {\r\n items: Record<string, any>[];\r\n defaultValues: any;\r\n attrs: Record<string, any>;\r\n};\r\n\r\nasync function init() {\r\n await prepareAlpineDefer(async (Alpine) => {\r\n useCssImport('@vue-animate');\r\n\r\n Alpine.data('RepeatableField', ({ items, defaultValues, attrs }: RepeatableParams, options: RepeatableOptions) => ({\r\n items,\r\n defaultValues,\r\n attrs,\r\n options: mergeDeep<RepeatableOptions>(defaultOptions, options),\r\n init() {\r\n // this.items = this.items.filter((item) => item !== '__EMPTY_ARRAY__');\r\n\r\n if (this.options.sortable) {\r\n // @see https://github.com/alpinejs/alpine/discussions/1635\r\n import('sortablejs').then(({ default: Sortable }) => {\r\n Sortable.create(this.$refs.tbody, {\r\n handle: '.h-handle',\r\n animation: 300,\r\n onEnd: (event: any) => {\r\n // V3 helper to unwrap the proxy\r\n const items = Alpine.raw(this.items);\r\n\r\n // splice mutates the original object, which\r\n // you want to avoid. In this case it works because we\r\n // created a temporary object that we can control\r\n // That way we know there are no side effects\r\n const droppedAtItem = items.splice(event.oldIndex, 1)[0];\r\n items.splice(event.newIndex, 0, droppedAtItem);\r\n //\r\n // // Alpine will update when you modify the state,\r\n // // so we need to set it back to our new state\r\n this.items = items;\r\n\r\n // HACK update prevKeys to new sort order\r\n let keys = [];\r\n for (let item of items) {\r\n keys.push(item.uid);\r\n }\r\n\r\n // HACK update index of dataStack\r\n // @ts-ignore\r\n this.$refs.steps_template._x_prevKeys = keys;\r\n // @ts-ignore\r\n const elements = this.$refs.steps_template\r\n .parentElement\r\n .querySelectorAll('tr');\r\n\r\n [].slice.call(elements).forEach((ele, i) => {\r\n // @ts-ignore\r\n if (ele?._x_dataStack[0]?.i != null) {\r\n // @ts-ignore\r\n ele._x_dataStack[0].i = i;\r\n }\r\n });\r\n }\r\n });\r\n });\r\n }\r\n\r\n this.items.forEach(prepareItem);\r\n\r\n if (this.options.ensureFirstRow) {\r\n this.ensureFirstRow();\r\n }\r\n },\r\n\r\n addItem(i: number) {\r\n const item = prepareItem(this.getEmptyItem());\r\n\r\n this.items.splice(i + 1, 0, item);\r\n },\r\n\r\n delItem(i: number) {\r\n const el = this.getItemElementByUID(this.items[i].uid);\r\n let hasAnimate = false;\r\n\r\n el?.addEventListener('animationstart', () => {\r\n hasAnimate = true;\r\n }, { once: true });\r\n\r\n el?.classList.add('animate__fadeOut');\r\n\r\n setTimeout(() => {\r\n if (!hasAnimate) {\r\n this._removeItem(i);\r\n }\r\n }, 100);\r\n\r\n el?.addEventListener('animationend', () => {\r\n this._removeItem(i);\r\n }, { once: true });\r\n },\r\n\r\n _removeItem(i: number) {\r\n this.items.splice(i, 1);\r\n\r\n if (this.options.ensureFirstRow) {\r\n this.ensureFirstRow();\r\n }\r\n },\r\n\r\n ensureFirstRow() {\r\n if (this.items.length === 0) {\r\n this.items.push(prepareItem(this.getEmptyItem()));\r\n }\r\n },\r\n\r\n getItemElementByUID(uid: string) {\r\n return this.$root.querySelector(`[data-item=\"${uid}\"]`);\r\n },\r\n\r\n getId(i: number, item: any, field: string) {\r\n return `${this.id}-${item.uid}-${field}`;\r\n },\r\n\r\n getName(i: number, item: any, field: string) {\r\n if (this.options.singleArray) {\r\n if (this.options.hasKey) {\r\n if (field === 'key') {\r\n return '';\r\n }\r\n\r\n return `${this.fieldName}[${item.key}]`;\r\n }\r\n\r\n return `${this.fieldName}[]`;\r\n }\r\n\r\n return `${this.fieldName}[${i}][${field}]`;\r\n },\r\n\r\n getEmptyItem() {\r\n return cloneDeep(this.defaultValues);\r\n },\r\n\r\n get canAdd() {\r\n if (!this.options.max) {\r\n return true;\r\n }\r\n\r\n return this.options.max > this.items.length;\r\n },\r\n\r\n get canModify() {\r\n return this.attrs.disabled == null && this.attrs.readonly == null;\r\n },\r\n\r\n get fieldName() {\r\n return this.options.fieldName;\r\n },\r\n\r\n get id() {\r\n return this.options.id;\r\n }\r\n }));\r\n });\r\n\r\n await initAlpineComponent('data-repeatable');\r\n}\r\n\r\nexport const ready = init();\r\n\r\nexport interface RepeatableModule {\r\n ready: typeof ready;\r\n}\r\n"],"names":["items","uid"],"mappings":"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"}
1
+ {"version":3,"file":"field-repeatable.js","sources":["../../src/module/field-repeatable.ts"],"sourcesContent":["import { cloneDeep } from 'lodash-es';\nimport { initAlpineComponent, prepareAlpineDefer, uid, useCssImport } from '../service';\nimport { mergeDeep } from '../utilities';\n\nexport interface RepeatableOptions {\n id?: string;\n fieldName?: string;\n sortable?: boolean;\n hasKey?: boolean;\n singleArray?: boolean;\n ensureFirstRow?: boolean;\n max?: number | null;\n}\n\nconst defaultOptions: RepeatableOptions = {\n id: '',\n fieldName: '',\n sortable: false,\n hasKey: false,\n singleArray: false,\n ensureFirstRow: false,\n max: null,\n};\n\nfunction prepareItem(item: any) {\n if (item.uid == null) {\n item.uid = uid();\n }\n return item;\n}\n\ntype RepeatableParams = {\n items: Record<string, any>[];\n defaultValues: any;\n attrs: Record<string, any>;\n};\n\nasync function init() {\n await prepareAlpineDefer(async (Alpine) => {\n useCssImport('@vue-animate');\n\n Alpine.data('RepeatableField', ({ items, defaultValues, attrs }: RepeatableParams, options: RepeatableOptions) => ({\n items,\n defaultValues,\n attrs,\n options: mergeDeep<RepeatableOptions>(defaultOptions, options),\n init() {\n // this.items = this.items.filter((item) => item !== '__EMPTY_ARRAY__');\n\n if (this.options.sortable) {\n // @see https://github.com/alpinejs/alpine/discussions/1635\n import('sortablejs').then(({ default: Sortable }) => {\n Sortable.create(this.$refs.tbody, {\n handle: '.h-handle',\n animation: 300,\n onEnd: (event: any) => {\n // V3 helper to unwrap the proxy\n const items = Alpine.raw(this.items);\n\n // splice mutates the original object, which\n // you want to avoid. In this case it works because we\n // created a temporary object that we can control\n // That way we know there are no side effects\n const droppedAtItem = items.splice(event.oldIndex, 1)[0];\n items.splice(event.newIndex, 0, droppedAtItem);\n //\n // // Alpine will update when you modify the state,\n // // so we need to set it back to our new state\n this.items = items;\n\n // HACK update prevKeys to new sort order\n let keys = [];\n for (let item of items) {\n keys.push(item.uid);\n }\n\n // HACK update index of dataStack\n // @ts-ignore\n this.$refs.steps_template._x_prevKeys = keys;\n // @ts-ignore\n const elements = this.$refs.steps_template\n .parentElement\n .querySelectorAll('tr');\n\n [].slice.call(elements).forEach((ele, i) => {\n // @ts-ignore\n if (ele?._x_dataStack[0]?.i != null) {\n // @ts-ignore\n ele._x_dataStack[0].i = i;\n }\n });\n }\n });\n });\n }\n\n this.items.forEach(prepareItem);\n\n if (this.options.ensureFirstRow) {\n this.ensureFirstRow();\n }\n },\n\n addItem(i: number) {\n const item = prepareItem(this.getEmptyItem());\n\n this.items.splice(i + 1, 0, item);\n },\n\n delItem(i: number) {\n const el = this.getItemElementByUID(this.items[i].uid);\n let hasAnimate = false;\n\n el?.addEventListener('animationstart', () => {\n hasAnimate = true;\n }, { once: true });\n\n el?.classList.add('animate__fadeOut');\n\n setTimeout(() => {\n if (!hasAnimate) {\n this._removeItem(i);\n }\n }, 100);\n\n el?.addEventListener('animationend', () => {\n this._removeItem(i);\n }, { once: true });\n },\n\n _removeItem(i: number) {\n this.items.splice(i, 1);\n\n if (this.options.ensureFirstRow) {\n this.ensureFirstRow();\n }\n },\n\n ensureFirstRow() {\n if (this.items.length === 0) {\n this.items.push(prepareItem(this.getEmptyItem()));\n }\n },\n\n getItemElementByUID(uid: string) {\n return this.$root.querySelector(`[data-item=\"${uid}\"]`);\n },\n\n getId(i: number, item: any, field: string) {\n return `${this.id}-${item.uid}-${field}`;\n },\n\n getName(i: number, item: any, field: string) {\n if (this.options.singleArray) {\n if (this.options.hasKey) {\n if (field === 'key') {\n return '';\n }\n\n return `${this.fieldName}[${item.key}]`;\n }\n\n return `${this.fieldName}[]`;\n }\n\n return `${this.fieldName}[${i}][${field}]`;\n },\n\n getEmptyItem() {\n return cloneDeep(this.defaultValues);\n },\n\n get canAdd() {\n if (!this.options.max) {\n return true;\n }\n\n return this.options.max > this.items.length;\n },\n\n get canModify() {\n return this.attrs.disabled == null && this.attrs.readonly == null;\n },\n\n get fieldName() {\n return this.options.fieldName;\n },\n\n get id() {\n return this.options.id;\n }\n }));\n });\n\n await initAlpineComponent('data-repeatable');\n}\n\nexport const ready = init();\n\nexport interface RepeatableModule {\n ready: typeof ready;\n}\n"],"names":["items","uid"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-single-image-drag.js","sources":["../../src/module/field-single-image-drag.ts"],"sourcesContent":["\r\nimport { useHttpClient } from '../composable';\r\nimport { __, injectCssToDocument, selectAll, simpleAlert } from '../service';\r\nimport { mergeDeep } from '../utilities';\r\nimport css from '../../scss/field/single-image-drag.scss?inline';\r\nimport { Modal } from 'bootstrap';\r\nimport type Cropper from 'cropperjs';\r\nimport { ApiReturn } from './http-client';\r\n\r\nexport interface SingleImageDragOptions {\r\n accept: string | string[];\r\n ajax_url?: string;\r\n crop: boolean;\r\n width: number;\r\n height: number;\r\n max_width?: number;\r\n min_width?: number;\r\n max_height?: number;\r\n min_height?: number;\r\n modalTarget: string;\r\n}\r\n\r\nconst defaultOptions: Partial<SingleImageDragOptions> = {\r\n accept: [\r\n 'image/jpeg',\r\n 'image/png',\r\n 'image/webp',\r\n 'image/avif',\r\n 'image/gif',\r\n ],\r\n crop: false,\r\n width: 800,\r\n height: 800,\r\n};\r\n\r\nexport class SingleImageDragElement extends HTMLElement {\r\n static is = 'uni-sid';\r\n\r\n currentImage = '';\r\n currentFile: File | undefined = undefined;\r\n lastZoom = 0;\r\n valueBackup = '';\r\n\r\n private options!: SingleImageDragOptions;\r\n private valueInput!: HTMLInputElement;\r\n private fileInput!: HTMLInputElement;\r\n private selectButton!: HTMLButtonElement;\r\n private pasteButton!: HTMLButtonElement;\r\n private dragarea!: HTMLDivElement;\r\n private previewImage!: HTMLImageElement;\r\n private removeCheckbox!: HTMLInputElement;\r\n private modalElement!: HTMLDivElement;\r\n private modal!: Modal;\r\n private cropContainer!: HTMLDivElement;\r\n private savebutton!: HTMLButtonElement;\r\n private modalToolbarButtons!: NodeListOf<HTMLButtonElement>;\r\n private cropper!: Cropper;\r\n\r\n constructor() {\r\n super();\r\n }\r\n\r\n connectedCallback() {\r\n this.options = mergeDeep(\r\n {},\r\n defaultOptions,\r\n JSON.parse(this.getAttribute('options') || '{}')\r\n );\r\n\r\n this.valueInput = this.querySelector<HTMLInputElement>('[data-field-input]')!;\r\n this.fileInput = this.querySelector<HTMLInputElement>('[data-sid=file]')!;\r\n this.selectButton = this.querySelector<HTMLButtonElement>('[data-sid=select]')!;\r\n this.pasteButton = this.querySelector<HTMLButtonElement>('[data-sid=paste]')!;\r\n this.dragarea = this.querySelector<HTMLDivElement>('[data-sid=dragarea]')!;\r\n this.previewImage = this.querySelector<HTMLImageElement>('[data-sid=preview]')!;\r\n this.removeCheckbox = this.querySelector<HTMLInputElement>('[data-sid=remove]')!;\r\n\r\n this.modalElement = document.querySelector<HTMLDivElement>(this.options.modalTarget)!;\r\n this.modal = Modal.getOrCreateInstance(this.modalElement);\r\n this.cropContainer = this.modalElement.querySelector<HTMLDivElement>('[data-sid=\"crop-container\"]')!;\r\n this.savebutton = this.modalElement.querySelector<HTMLButtonElement>('[data-sid=save-button]')!;\r\n this.modalToolbarButtons = this.modalElement.querySelectorAll<HTMLButtonElement>('[data-sid-toolbar]');\r\n\r\n const modalShown = async () => {\r\n const cropper = await this.getCropper();\r\n cropper.replace(this.currentImage);\r\n this.cropContainer.style.visibility = '';\r\n this.currentImage = '';\r\n };\r\n\r\n this.modalElement.addEventListener('shown.bs.modal', modalShown.bind(this));\r\n\r\n this.savebutton.addEventListener('click', () => {\r\n this.saveCropped();\r\n this.modal.hide();\r\n });\r\n\r\n this.bindEvents();\r\n\r\n this.style.visibility = '';\r\n }\r\n\r\n bindEvents() {\r\n this.dragarea.addEventListener('dragover', (event) => {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n this.dragarea.classList.add('hover');\r\n });\r\n\r\n this.dragarea.addEventListener('dragleave', (event) => {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n this.dragarea.classList.remove('hover');\r\n });\r\n\r\n this.dragarea.addEventListener('drop', (event) => {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n this.dragarea.classList.remove('hover');\r\n\r\n const files = (event.target as HTMLInputElement).files || event.dataTransfer?.files || [];\r\n this.handleFileSelect(files[0]);\r\n });\r\n\r\n // Select button\r\n this.selectButton.addEventListener('click', () => {\r\n const input = document.createElement('input');\r\n input.setAttribute('type', 'file');\r\n input.setAttribute('accept', this.getInputAccept());\r\n input.style.display = 'none';\r\n input.addEventListener('change', (e) => {\r\n this.handleFileSelect(input.files![0]!);\r\n\r\n input.remove();\r\n });\r\n\r\n document.body.appendChild(input);\r\n input.click();\r\n });\r\n\r\n this.pasteButton.addEventListener('click', () => {\r\n navigator.clipboard.read().then((items) => {\r\n let types = items[0].types;\r\n\r\n if (types.length === 0) {\r\n this.alert('This browser unable to get clipboard data.');\r\n return;\r\n }\r\n\r\n types = types.slice().sort();\r\n\r\n const type = types[0];\r\n\r\n items[0].getType(type).then((blob) => {\r\n this.handleFileSelect(new File([ blob ], 'image.png', { type }));\r\n });\r\n });\r\n });\r\n\r\n // Delete\r\n this.removeCheckbox?.addEventListener('click', () => {\r\n if (this.removeCheckbox.checked) {\r\n this.valueBackup = this.valueInput.value;\r\n this.valueInput.value = '';\r\n } else {\r\n this.valueInput.value = this.valueBackup;\r\n this.valueBackup = '';\r\n }\r\n });\r\n\r\n // Zoom slider\r\n selectAll(this.modalToolbarButtons, (button) => {\r\n button.addEventListener('click', (event) => {\r\n this.toolbarClicked(button, event);\r\n });\r\n });\r\n }\r\n\r\n getInputAccept() {\r\n let accept = this.options.accept;\r\n\r\n if (Array.isArray(accept)) {\r\n accept = accept.join(',');\r\n }\r\n\r\n return accept;\r\n }\r\n\r\n handleFileSelect(file: File) {\r\n if (!this.checkFile(file)) {\r\n return;\r\n }\r\n\r\n if (this.options.crop) {\r\n const reader = new FileReader();\r\n\r\n reader.addEventListener('load', (event) => {\r\n this.cropContainer.style.visibility = 'hidden';\r\n this.currentImage = event.target!.result as string;\r\n this.currentFile = file;\r\n\r\n // After modal shown, cropper will auto load.\r\n this.modal.show();\r\n });\r\n\r\n reader.readAsDataURL(file);\r\n return;\r\n }\r\n\r\n this.saveImage(file);\r\n }\r\n\r\n async saveCropped() {\r\n const Cropper = await this.getCropper();\r\n\r\n Cropper.getCroppedCanvas({\r\n width: this.options.width,\r\n height: this.options.height,\r\n imageSmoothingEnabled: true\r\n })\r\n .toBlob((blob) => {\r\n const file = new File([ blob! ], this.currentFile!.name, { type: 'image/png' });\r\n this.saveImage(file);\r\n }, 'image/png');\r\n }\r\n\r\n async getCropper() {\r\n if (this.cropper) {\r\n return this.cropper;\r\n }\r\n\r\n const Cropper = await loadCropper();\r\n\r\n return this.cropper = new Cropper(this.cropContainer.querySelector('img')!, {\r\n aspectRatio: this.options.width / this.options.height,\r\n autoCropArea: 1,\r\n viewMode: 1,\r\n dragMode: 'move',\r\n cropBoxMovable: false,\r\n cropBoxResizable: false,\r\n ready: (e) => {\r\n //\r\n },\r\n });\r\n }\r\n\r\n async toolbarClicked(button: HTMLButtonElement, event: MouseEvent) {\r\n const cropper = await this.getCropper();\r\n\r\n const data = cropper.getData();\r\n\r\n switch (button.dataset.sidToolbar) {\r\n case 'zoom-in':\r\n cropper.zoom(0.1);\r\n break;\r\n\r\n case 'zoom-out':\r\n cropper.zoom(-0.1);\r\n break;\r\n\r\n case 'rotate-left':\r\n cropper.rotate(-90);\r\n break;\r\n\r\n case 'rotate-right':\r\n cropper.rotate(90);\r\n break;\r\n\r\n case 'scale-x':\r\n cropper.scaleX(-data.scaleX);\r\n break;\r\n\r\n case 'scale-y':\r\n cropper.scaleY(-data.scaleY);\r\n break;\r\n }\r\n }\r\n\r\n checkFile(file: File): boolean {\r\n let accept = this.options.accept;\r\n\r\n if (typeof accept === 'string') {\r\n accept = accept.split(',').map(v => v.trim());\r\n }\r\n\r\n if (!accept.length) {\r\n return true;\r\n }\r\n\r\n let allow = false;\r\n\r\n for (const type of accept) {\r\n if (type.indexOf('/') !== -1) {\r\n allow = allow || this.compareMimeType(type, file.type);\r\n } else {\r\n allow = allow || type.toLowerCase() === getFileExtension(file)?.toLowerCase();\r\n }\r\n }\r\n\r\n if (allow) {\r\n return true;\r\n }\r\n\r\n this.alert(\r\n __('unicorn.field.sid.message.invalid.image.title'),\r\n __('unicorn.field.sid.message.invalid.image.desc'),\r\n 'error'\r\n );\r\n\r\n return false;\r\n }\r\n\r\n compareMimeType(accept: string, mime: string) {\r\n const accept2 = accept.split('/');\r\n const mime2 = mime.split('/');\r\n\r\n if (accept2[1] === '*') {\r\n return accept2[0] === mime2[0];\r\n }\r\n\r\n return accept === mime;\r\n }\r\n\r\n checkSize(image: HTMLImageElement): boolean {\r\n try {\r\n if (this.options.max_width && this.options.max_width < image.width) {\r\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.width', this.options.max_width));\r\n }\r\n\r\n if (this.options.min_width && this.options.min_width > image.width) {\r\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.width', this.options.min_width));\r\n }\r\n\r\n if (this.options.max_height && this.options.max_height < image.height) {\r\n throw new Error(__('unicorn.field.sid.message.invalid.size.max.height', this.options.max_height));\r\n }\r\n\r\n if (this.options.min_height && this.options.min_height > image.height) {\r\n throw new Error(__('unicorn.field.sid.message.invalid.size.min.height', this.options.min_height));\r\n }\r\n } catch (e) {\r\n this.alert(\r\n __('unicorn.field.sid.message.invalid.size.title'),\r\n (e as Error).message,\r\n 'error'\r\n );\r\n\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n alert(title: string, text = '', type = 'info') {\r\n return simpleAlert(title, text, type);\r\n }\r\n\r\n async saveImage(file: File) {\r\n if (this.options.ajax_url) {\r\n const loading = this.querySelector<HTMLImageElement>('[data-sid=file-uploading]')!;\r\n\r\n this.previewImage.src = '';\r\n this.previewImage.style.display = 'none';\r\n loading.style.display = 'flex';\r\n\r\n try {\r\n const res = await this.uploadImage(file);\r\n\r\n this.storeValue(res.data.data.url, res.data.data.url);\r\n } catch (e) {\r\n console.error(e);\r\n simpleAlert((e as Error).message);\r\n return;\r\n } finally {\r\n loading.style.display = 'none';\r\n }\r\n\r\n return;\r\n }\r\n\r\n // @see https://stackoverflow.com/a/47172409\r\n // @see https://stackoverflow.com/a/47522812\r\n const dt = new DataTransfer();\r\n dt.items.add(file);\r\n\r\n // No required for value input to remove validation message\r\n this.valueInput.required = false;\r\n\r\n this.fileInput.files = dt.files;\r\n this.fileInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\r\n this.fileInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\r\n\r\n this.storeValue('', URL.createObjectURL(file));\r\n }\r\n\r\n async uploadImage(file: File) {\r\n const formData = new FormData();\r\n formData.append('file', file);\r\n\r\n const { post } = await useHttpClient();\r\n\r\n return post<ApiReturn<{ url: string; }>>(this.options.ajax_url!, formData, {\r\n headers: {\r\n 'Content-Type': 'multipart/form-data'\r\n }\r\n });\r\n }\r\n\r\n storeValue(url: string, preview: string) {\r\n this.previewImage.src = preview;\r\n this.previewImage.style.display = 'inline-block';\r\n\r\n // Make delete box unchecked\r\n if (this.removeCheckbox) {\r\n this.removeCheckbox.checked = false;\r\n }\r\n\r\n if (url) {\r\n this.valueInput.value = url;\r\n }\r\n\r\n // Trigger change\r\n this.previewImage.dispatchEvent(new CustomEvent('change', { bubbles: true }));\r\n this.valueInput.dispatchEvent(new CustomEvent('change', { bubbles: true }));\r\n this.valueInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));\r\n }\r\n}\r\n\r\n// Promise.all([\r\n// import('@cropperjs/cropper.min.js'),\r\n// import('@cropperjs/cropper.css'),\r\n// ])\r\n// .then((service) => {\r\n// const styleSheet = service[1].default;\r\n// document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleSheet];\r\n// });\r\n\r\nfunction getFileExtension(file: File): string | undefined {\r\n const parts = file.name.split('.');\r\n if (parts.length > 1) {\r\n return parts.pop();\r\n }\r\n return undefined;\r\n}\r\n\r\nlet loadingCropper: Promise<any>;\r\n\r\nasync function loadCropper(): Promise<typeof Cropper> {\r\n loadingCropper ??= Promise.all([\r\n import('cropperjs'),\r\n import('cropperjs/dist/cropper.min.css?inline').then(({ default: css }) => {\r\n injectCssToDocument(css);\r\n })\r\n ]);\r\n\r\n return (await loadingCropper)[0];\r\n}\r\n\r\nasync function init() {\r\n injectCssToDocument(css);\r\n\r\n customElements.define(SingleImageDragElement.is, SingleImageDragElement);\r\n\r\n await loadCropper();\r\n}\r\n\r\nexport const ready = init();\r\n\r\nexport interface SingleImageDragModule {\r\n SingleImageDragElement: typeof SingleImageDragElement;\r\n ready: typeof ready;\r\n}\r\n"],"names":["css"],"mappings":"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"}
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;\n private pasteButton!: HTMLButtonElement;\n private dragarea!: HTMLDivElement;\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 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 // 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 return (await loadingCropper)[0];\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 +1 @@
1
- {"version":3,"file":"form.js","sources":["../../src/module/form.ts"],"sourcesContent":["import { data } from '../data';\r\nimport { loadAlpine, useSystemUri } from '../service';\r\nimport type { Nullable } from '../types';\r\n\r\nexport class UnicornFormElement {\r\n element: HTMLFormElement | undefined;\r\n options: Record<string, any>;\r\n\r\n constructor(\r\n selector?: string | Element,\r\n element?: HTMLFormElement,\r\n options: Record<string, any> = {},\r\n ) {\r\n // If form not found, create one\r\n if (!element) {\r\n element = document.createElement('form');\r\n\r\n if (typeof selector === 'string' && selector.startsWith('#')) {\r\n element.setAttribute('id', selector.substring(1));\r\n element.setAttribute('name', selector.substring(1));\r\n }\r\n\r\n element.setAttribute('method', 'post');\r\n element.setAttribute('enctype', 'multipart/form-data');\r\n element.setAttribute('novalidate', 'true');\r\n element.setAttribute('action', useSystemUri('full'));\r\n element.setAttribute('style', 'display: none;');\r\n\r\n const csrf = document.createElement('input');\r\n csrf.setAttribute('type', 'hidden');\r\n csrf.setAttribute('name', data('csrf-token'));\r\n csrf.setAttribute('value', '1');\r\n\r\n element.appendChild(csrf);\r\n document.body.appendChild(element);\r\n }\r\n\r\n this.element = element;\r\n this.options = { ...options };\r\n }\r\n\r\n initComponent(store = 'form', custom = {}) {\r\n return loadAlpine((Alpine) => {\r\n Alpine.store(store, this.useState(custom));\r\n });\r\n }\r\n\r\n useState(custom = {}) {\r\n const state: Record<string, any> = {};\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(this))\r\n .map(item => {\r\n // @ts-ignore\r\n return state[item] = this[item].bind(this);\r\n });\r\n\r\n return Object.assign(\r\n state,\r\n custom\r\n );\r\n }\r\n\r\n getElement() {\r\n return this.element;\r\n }\r\n\r\n submit(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n method?: Nullable<string>,\r\n customMethod?: Nullable<string>,\r\n ): boolean {\r\n const form = this.element!;\r\n\r\n if (customMethod) {\r\n let methodInput = form.querySelector<HTMLInputElement>('input[name=\"_method\"]');\r\n\r\n if (!methodInput) {\r\n methodInput = document.createElement('input');\r\n methodInput.setAttribute('name', '_method');\r\n methodInput.setAttribute('type', 'hidden');\r\n methodInput.value = customMethod;\r\n\r\n form.appendChild(methodInput);\r\n } else {\r\n methodInput.value = customMethod;\r\n }\r\n }\r\n\r\n // Set data into form.\r\n if (data) {\r\n const flatted = UnicornFormElement.flattenObject(data);\r\n\r\n for (const key in flatted) {\r\n const value = flatted[key];\r\n\r\n const fieldName = UnicornFormElement.buildFieldName(key);\r\n this.injectInput(fieldName, value);\r\n }\r\n }\r\n\r\n if (url) {\r\n form.setAttribute('action', url);\r\n }\r\n\r\n if (method) {\r\n form.setAttribute('method', method);\r\n }\r\n\r\n // Use requestSubmit() to fire submit event.\r\n form.requestSubmit();\r\n\r\n return true;\r\n }\r\n\r\n injectInput(name: string, value: any) {\r\n let input = this.element!.querySelector<HTMLInputElement>(`input[name=\"${name}\"]`);\r\n\r\n if (!input) {\r\n input = document.createElement('input');\r\n input.setAttribute('name', name);\r\n input.setAttribute('type', 'hidden');\r\n input.setAttribute('data-role', 'temp-input');\r\n\r\n this.element!.appendChild(input);\r\n }\r\n\r\n input.value = value;\r\n return input;\r\n }\r\n\r\n /**\r\n * Make a GET request.\r\n */\r\n get(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n customMethod?: Nullable<string>,\r\n ): boolean {\r\n return this.submit(url, data, 'GET', customMethod);\r\n }\r\n\r\n /**\r\n * Post form.\r\n */\r\n post(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n customMethod?: Nullable<string>,\r\n ) {\r\n customMethod = customMethod || 'POST';\r\n\r\n return this.submit(url, data, 'POST', customMethod);\r\n }\r\n\r\n /**\r\n * Make a PUT request.\r\n */\r\n put(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n ) {\r\n return this.post(url, data, 'PUT');\r\n }\r\n\r\n /**\r\n * Make a PATCH request.\r\n */\r\n patch(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n ) {\r\n return this.post(url, data, 'PATCH');\r\n }\r\n\r\n /**\r\n * Make a DELETE request.\r\n */\r\n delete(\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>,\r\n ) {\r\n return this.post(url, data, 'DELETE');\r\n }\r\n\r\n /**\r\n * @see https://stackoverflow.com/a/53739792\r\n *\r\n * @param {Object} ob\r\n * @returns {Object}\r\n */\r\n static flattenObject(ob: Record<string, any>): Record<string, any> {\r\n const toReturn: Record<string, any> = {};\r\n\r\n for (let i in ob) {\r\n if (!ob.hasOwnProperty(i)) {\r\n continue;\r\n }\r\n\r\n if ((typeof ob[i]) === 'object' && ob[i] != null) {\r\n const flatObject = this.flattenObject(ob[i]);\r\n\r\n for (let x in flatObject) {\r\n if (!flatObject.hasOwnProperty(x)) {\r\n continue;\r\n }\r\n\r\n toReturn[i + '/' + x] = flatObject[x];\r\n }\r\n } else {\r\n toReturn[i] = ob[i];\r\n }\r\n }\r\n return toReturn;\r\n }\r\n\r\n static buildFieldName(field: string) {\r\n const names = field.split('/');\r\n\r\n const first = names.shift();\r\n\r\n return first + names.map(name => `[${name}]`).join('');\r\n }\r\n}\r\n"],"names":["data"],"mappings":"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"}
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', data('csrf-token'));\n csrf.setAttribute('value', '1');\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 /**\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 +1 @@
1
- {"version":3,"file":"grid.js","sources":["../../src/module/grid.ts"],"sourcesContent":["import { __, deleteConfirm, h, loadAlpine, simpleAlert, simpleConfirm, slideDown, slideUp } from '../service';\r\nimport { Nullable } from '../types';\r\nimport type { UnicornFormElement } from './form';\r\n\r\nexport class UnicornGridElement {\r\n options: Record<string, any>;\r\n ordering = '';\r\n state = {};\r\n\r\n constructor(\r\n selector: string,\r\n public element: HTMLElement,\r\n public form: UnicornFormElement,\r\n options: Record<string, any> = {}\r\n ) {\r\n this.options = { ...options };\r\n\r\n this.bindEvents();\r\n }\r\n\r\n bindEvents() {\r\n const inputs = this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox]');\r\n\r\n for (const ch of inputs) {\r\n ch.addEventListener('click', () => {\r\n ch.dispatchEvent(new CustomEvent('change'));\r\n });\r\n ch.addEventListener('change', () => {\r\n const event = new CustomEvent('unicorn:checked', {\r\n detail: { grid: this }\r\n });\r\n\r\n this.form.element?.dispatchEvent(event);\r\n });\r\n }\r\n }\r\n\r\n initComponent(store = 'grid', custom: Record<string, string> = {}) {\r\n this.ordering = this.element?.dataset?.ordering || '';\r\n\r\n if (this.ordering) {\r\n if (!this.ordering.toLowerCase().endsWith(' asc')\r\n && !this.ordering.toLowerCase().endsWith(' desc')) {\r\n this.ordering += ' ASC';\r\n }\r\n }\r\n\r\n return loadAlpine((Alpine) => {\r\n Alpine.store(store, this.useState(custom));\r\n });\r\n }\r\n\r\n useState(this: any, custom: Record<string, any> = {}) {\r\n const state: Partial<Record<string, any>> = {\r\n form: this.form.useState(custom),\r\n };\r\n\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(this))\r\n .map(item => {\r\n const prop = this[item];\r\n\r\n if (typeof prop === 'function') {\r\n return state[item] = this[item].bind(this);\r\n }\r\n\r\n return item;\r\n });\r\n\r\n return Object.assign(\r\n state,\r\n custom\r\n );\r\n }\r\n\r\n getElement() {\r\n return this.element;\r\n }\r\n\r\n sendFilter($event?: Event, method?: string) {\r\n if ($event) {\r\n $event.preventDefault();\r\n }\r\n\r\n this.form.submit(null, null, method);\r\n }\r\n\r\n clearFilters(element: HTMLElement, method?: Nullable<string>): void {\r\n element.querySelectorAll('input, textarea, select').forEach((ele) => {\r\n (ele as HTMLInputElement).value = '';\r\n });\r\n\r\n this.form.submit(null, null, method);\r\n }\r\n\r\n async toggleFilters(open: boolean, filterForm: HTMLElement) {\r\n if (open) {\r\n await slideDown(filterForm);\r\n } else {\r\n await slideUp(filterForm);\r\n }\r\n }\r\n\r\n sort($el: HTMLElement): boolean {\r\n const dir = this.getDirection($el);\r\n\r\n const field = $el.dataset.field;\r\n let asc = $el.dataset.asc;\r\n let desc = $el.dataset.desc;\r\n\r\n if (field) {\r\n asc = field + ' ASC';\r\n desc = field + ' DESC';\r\n }\r\n\r\n if (dir === 'ASC') {\r\n return this.sortBy(desc);\r\n }\r\n\r\n return this.sortBy(asc);\r\n }\r\n\r\n /**\r\n * Sort two items.\r\n */\r\n sortBy(ordering: Nullable<string>): boolean {\r\n if (!ordering) {\r\n return false;\r\n }\r\n\r\n let orderingInput = this.element.querySelector<HTMLInputElement>('input[name=list_ordering]');\r\n\r\n if (!orderingInput) {\r\n orderingInput = h('input', { name: 'list_ordering', type: 'hidden', value: '' });\r\n\r\n this.element.appendChild(orderingInput);\r\n }\r\n\r\n orderingInput.value = ordering;\r\n\r\n return this.form.put();\r\n }\r\n\r\n isSortActive($el: HTMLElement): boolean {\r\n return this.getDirection($el) != null;\r\n }\r\n\r\n getDirection($el: HTMLElement): \"ASC\" | \"DESC\" | null {\r\n const field = $el.dataset.field;\r\n let asc = $el.dataset.asc;\r\n let desc = $el.dataset.desc;\r\n\r\n if (field) {\r\n asc = field + ' ASC';\r\n desc = field + ' DESC';\r\n }\r\n\r\n if (this.orderingEquals(asc, this.ordering)) {\r\n return 'ASC';\r\n } else if (this.orderingEquals(desc, this.ordering)) {\r\n return 'DESC';\r\n }\r\n\r\n return null;\r\n }\r\n\r\n orderingEquals(a: Nullable<string>, b: Nullable<string>): boolean {\r\n a = a || '';\r\n b = b || '';\r\n\r\n a = a.replace(/\\s+/g, ' ').trim().toLowerCase();\r\n b = b.replace(/\\s+/g, ' ').trim().toLowerCase();\r\n\r\n return a === b;\r\n }\r\n\r\n /**\r\n * Check a row's checkbox.\r\n */\r\n checkRow(row: number, value = true): void {\r\n const ch = this.getCheckboxByRow(row);\r\n\r\n if (!ch) {\r\n throw new Error('Checkbox of row: ' + row + ' not found.');\r\n }\r\n\r\n ch.checked = value;\r\n ch.dispatchEvent(new Event('input'));\r\n ch.dispatchEvent(new Event('change'));\r\n }\r\n\r\n getCheckboxByRow(row: number): Nullable<HTMLInputElement> {\r\n return this.form.element?.querySelector<HTMLInputElement>(\r\n `input[data-role=grid-checkbox][data-row-number=\"${row}\"]`\r\n );\r\n }\r\n\r\n /**\r\n * Update a row.\r\n */\r\n updateRow(row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>) {\r\n const ch = this.getCheckboxByRow(row);\r\n\r\n if (!ch) {\r\n return false;\r\n }\r\n\r\n return this.updateItem(ch.value, url, data);\r\n }\r\n\r\n /**\r\n * Update an item by id.\r\n */\r\n updateItem(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n this.toggleAll(false);\r\n\r\n this.disableAllCheckboxes();\r\n\r\n this.form.injectInput('id[]', id);\r\n\r\n return this.form.patch(url, data);\r\n }\r\n\r\n /**\r\n * Update a item with batch task.\r\n */\r\n updateItemByTask(\r\n task: string,\r\n id: string | number,\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>\r\n ): boolean {\r\n data = data || {};\r\n data.task = task;\r\n\r\n return this.updateItem(id, url, data);\r\n }\r\n\r\n /**\r\n * @deprecated Use updateItemByTask() instead.\r\n */\r\n doTask(task: string, id: number | string, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n return this.updateItemByTask(task, id, url, data);\r\n }\r\n\r\n /**\r\n * Update a row with batch task.\r\n */\r\n updateRowByTask(task: string, row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n const ch = this.getCheckboxByRow(row);\r\n\r\n if (!ch) {\r\n return false;\r\n }\r\n\r\n return this.updateItemByTask(task, ch.value, url, data);\r\n }\r\n\r\n /**\r\n * Batch update items.\r\n */\r\n updateListByTask(task: string, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n data = data || {};\r\n data.task = task;\r\n\r\n return this.form.patch(url, data);\r\n }\r\n\r\n /**\r\n * Copy a row.\r\n */\r\n copyItem(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n this.toggleAll(false);\r\n\r\n this.disableAllCheckboxes();\r\n\r\n this.form.injectInput('id[]', id);\r\n\r\n return this.form.post(url, data);\r\n }\r\n\r\n /**\r\n * Copy a row.\r\n */\r\n copyRow(row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n const ch = this.getCheckboxByRow(row);\r\n\r\n if (!ch) {\r\n return false;\r\n }\r\n\r\n return this.copyItem(ch.value, url, data);\r\n }\r\n\r\n /**\r\n * Delete checked items.\r\n */\r\n deleteList(\r\n message?: Nullable<string> | false,\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>\r\n ): boolean {\r\n if (!this.validateChecked()) {\r\n return false;\r\n }\r\n\r\n message = message == null ? __('unicorn.message.delete.confirm') : message;\r\n\r\n if (message !== false) {\r\n simpleConfirm(message).then(isConfirm => {\r\n if (isConfirm) {\r\n this.form.delete(url, data);\r\n }\r\n });\r\n } else {\r\n this.form.delete(url, data);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Delete an item by row.\r\n */\r\n async deleteRow(row: number,\r\n msg?: Nullable<string>,\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>): Promise<boolean> {\r\n const ch = this.getCheckboxByRow(row);\r\n\r\n if (!ch) {\r\n return false;\r\n }\r\n\r\n return this.deleteItem(ch.value, msg, url, data);\r\n }\r\n\r\n /**\r\n * Delete an item.\r\n */\r\n async deleteItem(id: string,\r\n msg?: Nullable<string>,\r\n url?: Nullable<string>,\r\n data?: Nullable<Record<string, any>>): Promise<boolean> {\r\n msg = msg || __('unicorn.message.delete.confirm');\r\n\r\n const isConfirm = await deleteConfirm(msg);\r\n\r\n if (isConfirm) {\r\n // this.toggleAll(false);\r\n // this.checkRow(row);\r\n data = data || {};\r\n\r\n data.id = id;\r\n\r\n this.form.delete(url, data);\r\n }\r\n\r\n return isConfirm;\r\n }\r\n\r\n /**\r\n * Toggle all checkboxes.\r\n */\r\n toggleAll(value: boolean) {\r\n Array.from(\r\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]')\r\n )\r\n .forEach((input) => {\r\n input.checked = value;\r\n\r\n input.dispatchEvent(new CustomEvent('input'));\r\n input.dispatchEvent(new CustomEvent('change'));\r\n });\r\n\r\n return this;\r\n }\r\n\r\n disableAllCheckboxes() {\r\n Array.from(\r\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]')\r\n )\r\n .forEach((input) => {\r\n input.disabled = true;\r\n });\r\n }\r\n\r\n /**\r\n * Count checked checkboxes.\r\n */\r\n countChecked(): number {\r\n return this.getChecked().length;\r\n }\r\n\r\n /**\r\n * Get Checked boxes.\r\n */\r\n getChecked(): HTMLInputElement[] {\r\n return Array.from(\r\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]:checked')\r\n );\r\n }\r\n\r\n getCheckedValues(): string[] {\r\n return this.getChecked().map(input => input.value);\r\n }\r\n\r\n /**\r\n * Validate there has one or more checked boxes.\r\n */\r\n validateChecked(event?: Event, callback?: (grid: UnicornGridElement) => any, msg?: string): this {\r\n msg = msg || __('unicorn.message.grid.checked');\r\n\r\n if (!this.hasChecked()) {\r\n if (msg !== '') {\r\n simpleAlert(msg);\r\n }\r\n\r\n if (event) {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n\r\n return this;\r\n }\r\n\r\n if (callback) {\r\n callback(this);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n hasChecked(): boolean {\r\n return this.countChecked() > 0;\r\n }\r\n\r\n /**\r\n * Reorder all.\r\n */\r\n reorderAll(url?: Nullable<string>, data?: Nullable<Record<string, any>>) {\r\n return this.updateListByTask('reorder', url, data);\r\n }\r\n\r\n /**\r\n * Reorder items.\r\n */\r\n moveItem(id: number | string, delta: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n data = data || {};\r\n data.delta = delta;\r\n\r\n return this.updateItemByTask('move', id, url, data);\r\n }\r\n\r\n moveUp(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n return this.moveItem(id, -1, url, data);\r\n }\r\n\r\n moveDown(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\r\n return this.moveItem(id, 1, url, data);\r\n }\r\n\r\n getId(suffix = '') {\r\n return this.form.element?.id + suffix;\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grid.js","sources":["../../src/module/grid.ts"],"sourcesContent":["import { __, deleteConfirm, h, loadAlpine, simpleAlert, simpleConfirm, slideDown, slideUp } from '../service';\nimport { Nullable } from '../types';\nimport type { UnicornFormElement } from './form';\n\nexport class UnicornGridElement {\n options: Record<string, any>;\n ordering = '';\n state = {};\n\n constructor(\n selector: string,\n public element: HTMLElement,\n public form: UnicornFormElement,\n options: Record<string, any> = {}\n ) {\n this.options = { ...options };\n\n this.bindEvents();\n }\n\n bindEvents() {\n const inputs = this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox]');\n\n for (const ch of inputs) {\n ch.addEventListener('click', () => {\n ch.dispatchEvent(new CustomEvent('change'));\n });\n ch.addEventListener('change', () => {\n const event = new CustomEvent('unicorn:checked', {\n detail: { grid: this }\n });\n\n this.form.element?.dispatchEvent(event);\n });\n }\n }\n\n initComponent(store = 'grid', custom: Record<string, string> = {}) {\n this.ordering = this.element?.dataset?.ordering || '';\n\n if (this.ordering) {\n if (!this.ordering.toLowerCase().endsWith(' asc')\n && !this.ordering.toLowerCase().endsWith(' desc')) {\n this.ordering += ' ASC';\n }\n }\n\n return loadAlpine((Alpine) => {\n Alpine.store(store, this.useState(custom));\n });\n }\n\n useState(this: any, custom: Record<string, any> = {}) {\n const state: Partial<Record<string, any>> = {\n form: this.form.useState(custom),\n };\n\n Object.getOwnPropertyNames(Object.getPrototypeOf(this))\n .map(item => {\n const prop = this[item];\n\n if (typeof prop === 'function') {\n return state[item] = this[item].bind(this);\n }\n\n return item;\n });\n\n return Object.assign(\n state,\n custom\n );\n }\n\n getElement() {\n return this.element;\n }\n\n sendFilter($event?: Event, method?: string) {\n if ($event) {\n $event.preventDefault();\n }\n\n this.form.submit(null, null, method);\n }\n\n clearFilters(element: HTMLElement, method?: Nullable<string>): void {\n element.querySelectorAll('input, textarea, select').forEach((ele) => {\n (ele as HTMLInputElement).value = '';\n });\n\n this.form.submit(null, null, method);\n }\n\n async toggleFilters(open: boolean, filterForm: HTMLElement) {\n if (open) {\n await slideDown(filterForm);\n } else {\n await slideUp(filterForm);\n }\n }\n\n sort($el: HTMLElement): boolean {\n const dir = this.getDirection($el);\n\n const field = $el.dataset.field;\n let asc = $el.dataset.asc;\n let desc = $el.dataset.desc;\n\n if (field) {\n asc = field + ' ASC';\n desc = field + ' DESC';\n }\n\n if (dir === 'ASC') {\n return this.sortBy(desc);\n }\n\n return this.sortBy(asc);\n }\n\n /**\n * Sort two items.\n */\n sortBy(ordering: Nullable<string>): boolean {\n if (!ordering) {\n return false;\n }\n\n let orderingInput = this.element.querySelector<HTMLInputElement>('input[name=list_ordering]');\n\n if (!orderingInput) {\n orderingInput = h('input', { name: 'list_ordering', type: 'hidden', value: '' });\n\n this.element.appendChild(orderingInput);\n }\n\n orderingInput.value = ordering;\n\n return this.form.put();\n }\n\n isSortActive($el: HTMLElement): boolean {\n return this.getDirection($el) != null;\n }\n\n getDirection($el: HTMLElement): \"ASC\" | \"DESC\" | null {\n const field = $el.dataset.field;\n let asc = $el.dataset.asc;\n let desc = $el.dataset.desc;\n\n if (field) {\n asc = field + ' ASC';\n desc = field + ' DESC';\n }\n\n if (this.orderingEquals(asc, this.ordering)) {\n return 'ASC';\n } else if (this.orderingEquals(desc, this.ordering)) {\n return 'DESC';\n }\n\n return null;\n }\n\n orderingEquals(a: Nullable<string>, b: Nullable<string>): boolean {\n a = a || '';\n b = b || '';\n\n a = a.replace(/\\s+/g, ' ').trim().toLowerCase();\n b = b.replace(/\\s+/g, ' ').trim().toLowerCase();\n\n return a === b;\n }\n\n /**\n * Check a row's checkbox.\n */\n checkRow(row: number, value = true): void {\n const ch = this.getCheckboxByRow(row);\n\n if (!ch) {\n throw new Error('Checkbox of row: ' + row + ' not found.');\n }\n\n ch.checked = value;\n ch.dispatchEvent(new Event('input'));\n ch.dispatchEvent(new Event('change'));\n }\n\n getCheckboxByRow(row: number): Nullable<HTMLInputElement> {\n return this.form.element?.querySelector<HTMLInputElement>(\n `input[data-role=grid-checkbox][data-row-number=\"${row}\"]`\n );\n }\n\n /**\n * Update a row.\n */\n updateRow(row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>) {\n const ch = this.getCheckboxByRow(row);\n\n if (!ch) {\n return false;\n }\n\n return this.updateItem(ch.value, url, data);\n }\n\n /**\n * Update an item by id.\n */\n updateItem(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n this.toggleAll(false);\n\n this.disableAllCheckboxes();\n\n this.form.injectInput('id[]', id);\n\n return this.form.patch(url, data);\n }\n\n /**\n * Update a item with batch task.\n */\n updateItemByTask(\n task: string,\n id: string | number,\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>\n ): boolean {\n data = data || {};\n data.task = task;\n\n return this.updateItem(id, url, data);\n }\n\n /**\n * @deprecated Use updateItemByTask() instead.\n */\n doTask(task: string, id: number | string, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n return this.updateItemByTask(task, id, url, data);\n }\n\n /**\n * Update a row with batch task.\n */\n updateRowByTask(task: string, row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n const ch = this.getCheckboxByRow(row);\n\n if (!ch) {\n return false;\n }\n\n return this.updateItemByTask(task, ch.value, url, data);\n }\n\n /**\n * Batch update items.\n */\n updateListByTask(task: string, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n data = data || {};\n data.task = task;\n\n return this.form.patch(url, data);\n }\n\n /**\n * Copy a row.\n */\n copyItem(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n this.toggleAll(false);\n\n this.disableAllCheckboxes();\n\n this.form.injectInput('id[]', id);\n\n return this.form.post(url, data);\n }\n\n /**\n * Copy a row.\n */\n copyRow(row: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n const ch = this.getCheckboxByRow(row);\n\n if (!ch) {\n return false;\n }\n\n return this.copyItem(ch.value, url, data);\n }\n\n /**\n * Delete checked items.\n */\n deleteList(\n message?: Nullable<string> | false,\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>\n ): boolean {\n if (!this.validateChecked()) {\n return false;\n }\n\n message = message == null ? __('unicorn.message.delete.confirm') : message;\n\n if (message !== false) {\n simpleConfirm(message).then(isConfirm => {\n if (isConfirm) {\n this.form.delete(url, data);\n }\n });\n } else {\n this.form.delete(url, data);\n }\n\n return true;\n }\n\n /**\n * Delete an item by row.\n */\n async deleteRow(row: number,\n msg?: Nullable<string>,\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>): Promise<boolean> {\n const ch = this.getCheckboxByRow(row);\n\n if (!ch) {\n return false;\n }\n\n return this.deleteItem(ch.value, msg, url, data);\n }\n\n /**\n * Delete an item.\n */\n async deleteItem(id: string,\n msg?: Nullable<string>,\n url?: Nullable<string>,\n data?: Nullable<Record<string, any>>): Promise<boolean> {\n msg = msg || __('unicorn.message.delete.confirm');\n\n const isConfirm = await deleteConfirm(msg);\n\n if (isConfirm) {\n // this.toggleAll(false);\n // this.checkRow(row);\n data = data || {};\n\n data.id = id;\n\n this.form.delete(url, data);\n }\n\n return isConfirm;\n }\n\n /**\n * Toggle all checkboxes.\n */\n toggleAll(value: boolean) {\n Array.from(\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]')\n )\n .forEach((input) => {\n input.checked = value;\n\n input.dispatchEvent(new CustomEvent('input'));\n input.dispatchEvent(new CustomEvent('change'));\n });\n\n return this;\n }\n\n disableAllCheckboxes() {\n Array.from(\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]')\n )\n .forEach((input) => {\n input.disabled = true;\n });\n }\n\n /**\n * Count checked checkboxes.\n */\n countChecked(): number {\n return this.getChecked().length;\n }\n\n /**\n * Get Checked boxes.\n */\n getChecked(): HTMLInputElement[] {\n return Array.from(\n this.element.querySelectorAll<HTMLInputElement>('input[data-role=grid-checkbox][type=checkbox]:checked')\n );\n }\n\n getCheckedValues(): string[] {\n return this.getChecked().map(input => input.value);\n }\n\n /**\n * Validate there has one or more checked boxes.\n */\n validateChecked(event?: Event, callback?: (grid: UnicornGridElement) => any, msg?: string): this {\n msg = msg || __('unicorn.message.grid.checked');\n\n if (!this.hasChecked()) {\n if (msg !== '') {\n simpleAlert(msg);\n }\n\n if (event) {\n event.stopPropagation();\n event.preventDefault();\n }\n\n return this;\n }\n\n if (callback) {\n callback(this);\n }\n\n return this;\n }\n\n hasChecked(): boolean {\n return this.countChecked() > 0;\n }\n\n /**\n * Reorder all.\n */\n reorderAll(url?: Nullable<string>, data?: Nullable<Record<string, any>>) {\n return this.updateListByTask('reorder', url, data);\n }\n\n /**\n * Reorder items.\n */\n moveItem(id: number | string, delta: number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n data = data || {};\n data.delta = delta;\n\n return this.updateItemByTask('move', id, url, data);\n }\n\n moveUp(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n return this.moveItem(id, -1, url, data);\n }\n\n moveDown(id: string | number, url?: Nullable<string>, data?: Nullable<Record<string, any>>): boolean {\n return this.moveItem(id, 1, url, data);\n }\n\n getId(suffix = '') {\n return this.form.element?.id + suffix;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-client.js","sources":["../../../../../../node_modules/url-template/lib/url-template.js","../../src/module/http-client.ts"],"sourcesContent":["function encodeReserved(str) {\n return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {\n if (!/%[0-9A-Fa-f]/.test(part)) {\n part = encodeURI(part).replace(/%5B/g, '[').replace(/%5D/g, ']');\n }\n return part;\n }).join('');\n}\n\nfunction encodeUnreserved(str) {\n return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {\n return '%' + c.charCodeAt(0).toString(16).toUpperCase();\n });\n}\n\nfunction encodeValue(operator, value, key) {\n value = (operator === '+' || operator === '#') ? encodeReserved(value) : encodeUnreserved(value);\n\n if (key) {\n return encodeUnreserved(key) + '=' + value;\n } else {\n return value;\n }\n}\n\nfunction isDefined(value) {\n return value !== undefined && value !== null;\n}\n\nfunction isKeyOperator(operator) {\n return operator === ';' || operator === '&' || operator === '?';\n}\n\nfunction getValues(context, operator, key, modifier) {\n var value = context[key],\n result = [];\n\n if (isDefined(value) && value !== '') {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n value = value.toString();\n\n if (modifier && modifier !== '*') {\n value = value.substring(0, parseInt(modifier, 10));\n }\n\n result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));\n } else {\n if (modifier === '*') {\n if (Array.isArray(value)) {\n value.filter(isDefined).forEach(function (value) {\n result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));\n });\n } else {\n Object.keys(value).forEach(function (k) {\n if (isDefined(value[k])) {\n result.push(encodeValue(operator, value[k], k));\n }\n });\n }\n } else {\n var tmp = [];\n\n if (Array.isArray(value)) {\n value.filter(isDefined).forEach(function (value) {\n tmp.push(encodeValue(operator, value));\n });\n } else {\n Object.keys(value).forEach(function (k) {\n if (isDefined(value[k])) {\n tmp.push(encodeUnreserved(k));\n tmp.push(encodeValue(operator, value[k].toString()));\n }\n });\n }\n\n if (isKeyOperator(operator)) {\n result.push(encodeUnreserved(key) + '=' + tmp.join(','));\n } else if (tmp.length !== 0) {\n result.push(tmp.join(','));\n }\n }\n }\n } else {\n if (operator === ';') {\n if (isDefined(value)) {\n result.push(encodeUnreserved(key));\n }\n } else if (value === '' && (operator === '&' || operator === '?')) {\n result.push(encodeUnreserved(key) + '=');\n } else if (value === '') {\n result.push('');\n }\n }\n return result;\n}\n\nexport function parseTemplate(template) {\n var operators = ['+', '#', '.', '/', ';', '?', '&'];\n\n return {\n expand: function (context) {\n return template.replace(/\\{([^\\{\\}]+)\\}|([^\\{\\}]+)/g, function (_, expression, literal) {\n if (expression) {\n var operator = null,\n values = [];\n\n if (operators.indexOf(expression.charAt(0)) !== -1) {\n operator = expression.charAt(0);\n expression = expression.substr(1);\n }\n\n expression.split(/,/g).forEach(function (variable) {\n var tmp = /([^:\\*]*)(?::(\\d+)|(\\*))?/.exec(variable);\n values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3]));\n });\n\n if (operator && operator !== '+') {\n var separator = ',';\n\n if (operator === '?') {\n separator = '&';\n } else if (operator !== '#') {\n separator = operator;\n }\n return (values.length !== 0 ? operator : '') + values.join(separator);\n } else {\n return values.join(',');\n }\n } else {\n return encodeReserved(literal);\n }\n });\n }\n };\n}\n","import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults } from 'axios';\r\nimport AxiosStatic, { AxiosError, isAxiosError, isCancel } from 'axios';\r\nimport { parseTemplate } from 'url-template';\r\nimport { data } from '../data';\r\nimport { route } from '../service';\r\n\r\nexport interface ApiReturn<T = any> {\r\n success: boolean;\r\n message?: string;\r\n code: number;\r\n status: number;\r\n data: T;\r\n}\r\n\r\ndeclare module 'axios' {\r\n export interface AxiosRequestConfig {\r\n vars?: Record<string, any>;\r\n methodSimulate?: string;\r\n methodSimulateByHeader?: boolean;\r\n }\r\n\r\n export interface CreateAxiosDefaults {\r\n }\r\n}\r\n\r\nfunction prepareAxios(axios: AxiosInstance): AxiosInstance {\r\n axios.interceptors.request.use((config) => {\r\n config.headers['X-CSRF-Token'] = data('csrf-token');\r\n\r\n if (config.url && config.url.startsWith('@')) {\r\n config.url = route(config.url);\r\n }\r\n\r\n if (config?.vars && config.url) {\r\n const tmpl = parseTemplate(config.url);\r\n config.url = tmpl.expand(config.vars || {});\r\n }\r\n\r\n // Simulate methods\r\n if (config.methodSimulate) {\r\n if (config.methodSimulateByHeader) {\r\n config.headers['X-HTTP-Method-Override'] = config;\r\n } else if (typeof config.data === 'object') {\r\n config.data['_method'] = config.method;\r\n } else if (typeof config.data === 'string') {\r\n if (config.data.includes('?')) {\r\n config.data += '&_method=' + config.method;\r\n } else {\r\n config.data += '?_method=' + config.method;\r\n }\r\n }\r\n\r\n if (config.method?.toLowerCase() !== 'get') {\r\n config.method = 'POST';\r\n }\r\n }\r\n\r\n return config;\r\n });\r\n\r\n return axios;\r\n}\r\n\r\nexport type UnicornHttpClient = ReturnType<typeof createHttpClient>;\r\n\r\nexport function createHttpClient(config?: CreateAxiosDefaults | AxiosInstance) {\r\n const axios = config && 'interceptors' in config\r\n ? config\r\n : AxiosStatic.create(config ?? {});\r\n\r\n prepareAxios(axios);\r\n\r\n function requestMiddleware(callback: Parameters<AxiosInstance['interceptors']['request']['use']>[0]) {\r\n return axios.interceptors.request.use(callback);\r\n }\r\n\r\n function responseMiddleware(callback: Parameters<AxiosInstance['interceptors']['response']['use']>[0]) {\r\n return axios.interceptors.response.use(callback);\r\n }\r\n\r\n /**\r\n * Send a GET request.\r\n */\r\n async function get<T = any, D = any>(\r\n url: string,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'GET';\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a POST request.\r\n */\r\n async function post<T = any, D = any>(\r\n url: string,\r\n data?: any,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'POST';\r\n options.data = data;\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a PUT request.\r\n *\r\n * @param {string} url\r\n * @param {any} data\r\n * @param {AxiosRequestConfig} options\r\n *\r\n * @returns {Promise<AxiosResponse>}\r\n */\r\n async function put<T = any, D = any>(\r\n url: string,\r\n data?: any,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'PUT';\r\n options.data = data;\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a PATCH request.\r\n *\r\n * @param {string} url\r\n * @param {any} data\r\n * @param {AxiosRequestConfig} options\r\n *\r\n * @returns {Promise<AxiosResponse>}\r\n */\r\n async function patch<T = any, D = any>(\r\n url: string,\r\n data?: any,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'PATCH';\r\n options.data = data;\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a DELETE request.\r\n *\r\n * @param {string} url\r\n * @param {any} data\r\n * @param {AxiosRequestConfig} options\r\n *\r\n * @returns {Promise<AxiosResponse>}\r\n */\r\n async function deletes<T = any, D = any>(\r\n url: string,\r\n data?: any,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'DELETE';\r\n options.data = data;\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a HEAD request.\r\n *\r\n * @param {string} url\r\n * @param {AxiosRequestConfig} options\r\n *\r\n * @returns {Promise<AxiosResponse>}\r\n */\r\n async function head<T = any, D = any>(\r\n url: string,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'HEAD';\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send a OPTIONS request.\r\n *\r\n * @param {string} url\r\n * @param {AxiosRequestConfig} options\r\n *\r\n * @returns {Promise<AxiosResponse>}\r\n */\r\n async function options<T = any, D = any>(\r\n url: string,\r\n options: Partial<AxiosRequestConfig> = {}\r\n ): Promise<AxiosResponse<T, D>> {\r\n options.url = url;\r\n options.method = 'OPTIONS';\r\n\r\n return request(options);\r\n }\r\n\r\n /**\r\n * Send request.\r\n */\r\n async function request<T = any, D = any>(options: AxiosRequestConfig): Promise<AxiosResponse<T, D>> {\r\n try {\r\n return await axios(options);\r\n } catch (e) {\r\n (e as any).originMessage = (e as Error).message;\r\n\r\n const err = e as AxiosError<any>;\r\n\r\n if (err.response?.data?.message) {\r\n err.message = err.response.data.message;\r\n }\r\n\r\n throw err;\r\n }\r\n }\r\n\r\n return {\r\n axios,\r\n request,\r\n get,\r\n post,\r\n put,\r\n patch,\r\n delete: deletes,\r\n head,\r\n options,\r\n requestMiddleware,\r\n responseMiddleware,\r\n isCancel,\r\n AxiosError,\r\n isAxiosError,\r\n };\r\n}\r\n\r\nexport interface UnicornHttpModule {\r\n UnicornHttpClient: UnicornHttpClient;\r\n createHttpClient: typeof createHttpClient;\r\n}\r\n"],"names":["value","options","data"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"http-client.js","sources":["../../../../../../node_modules/url-template/lib/url-template.js","../../src/module/http-client.ts"],"sourcesContent":["function encodeReserved(str) {\n return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {\n if (!/%[0-9A-Fa-f]/.test(part)) {\n part = encodeURI(part).replace(/%5B/g, '[').replace(/%5D/g, ']');\n }\n return part;\n }).join('');\n}\n\nfunction encodeUnreserved(str) {\n return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {\n return '%' + c.charCodeAt(0).toString(16).toUpperCase();\n });\n}\n\nfunction encodeValue(operator, value, key) {\n value = (operator === '+' || operator === '#') ? encodeReserved(value) : encodeUnreserved(value);\n\n if (key) {\n return encodeUnreserved(key) + '=' + value;\n } else {\n return value;\n }\n}\n\nfunction isDefined(value) {\n return value !== undefined && value !== null;\n}\n\nfunction isKeyOperator(operator) {\n return operator === ';' || operator === '&' || operator === '?';\n}\n\nfunction getValues(context, operator, key, modifier) {\n var value = context[key],\n result = [];\n\n if (isDefined(value) && value !== '') {\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n value = value.toString();\n\n if (modifier && modifier !== '*') {\n value = value.substring(0, parseInt(modifier, 10));\n }\n\n result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));\n } else {\n if (modifier === '*') {\n if (Array.isArray(value)) {\n value.filter(isDefined).forEach(function (value) {\n result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));\n });\n } else {\n Object.keys(value).forEach(function (k) {\n if (isDefined(value[k])) {\n result.push(encodeValue(operator, value[k], k));\n }\n });\n }\n } else {\n var tmp = [];\n\n if (Array.isArray(value)) {\n value.filter(isDefined).forEach(function (value) {\n tmp.push(encodeValue(operator, value));\n });\n } else {\n Object.keys(value).forEach(function (k) {\n if (isDefined(value[k])) {\n tmp.push(encodeUnreserved(k));\n tmp.push(encodeValue(operator, value[k].toString()));\n }\n });\n }\n\n if (isKeyOperator(operator)) {\n result.push(encodeUnreserved(key) + '=' + tmp.join(','));\n } else if (tmp.length !== 0) {\n result.push(tmp.join(','));\n }\n }\n }\n } else {\n if (operator === ';') {\n if (isDefined(value)) {\n result.push(encodeUnreserved(key));\n }\n } else if (value === '' && (operator === '&' || operator === '?')) {\n result.push(encodeUnreserved(key) + '=');\n } else if (value === '') {\n result.push('');\n }\n }\n return result;\n}\n\nexport function parseTemplate(template) {\n var operators = ['+', '#', '.', '/', ';', '?', '&'];\n\n return {\n expand: function (context) {\n return template.replace(/\\{([^\\{\\}]+)\\}|([^\\{\\}]+)/g, function (_, expression, literal) {\n if (expression) {\n var operator = null,\n values = [];\n\n if (operators.indexOf(expression.charAt(0)) !== -1) {\n operator = expression.charAt(0);\n expression = expression.substr(1);\n }\n\n expression.split(/,/g).forEach(function (variable) {\n var tmp = /([^:\\*]*)(?::(\\d+)|(\\*))?/.exec(variable);\n values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3]));\n });\n\n if (operator && operator !== '+') {\n var separator = ',';\n\n if (operator === '?') {\n separator = '&';\n } else if (operator !== '#') {\n separator = operator;\n }\n return (values.length !== 0 ? operator : '') + values.join(separator);\n } else {\n return values.join(',');\n }\n } else {\n return encodeReserved(literal);\n }\n });\n }\n };\n}\n","import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults } from 'axios';\nimport AxiosStatic, { AxiosError, isAxiosError, isCancel } from 'axios';\nimport { parseTemplate } from 'url-template';\nimport { data } from '../data';\nimport { route } from '../service';\n\nexport interface ApiReturn<T = any> {\n success: boolean;\n message?: string;\n code: number;\n status: number;\n data: T;\n}\n\ndeclare module 'axios' {\n export interface AxiosRequestConfig {\n vars?: Record<string, any>;\n methodSimulate?: string;\n methodSimulateByHeader?: boolean;\n }\n\n export interface CreateAxiosDefaults {\n }\n}\n\nfunction prepareAxios(axios: AxiosInstance): AxiosInstance {\n axios.interceptors.request.use((config) => {\n config.headers['X-CSRF-Token'] = data('csrf-token');\n\n if (config.url && config.url.startsWith('@')) {\n config.url = route(config.url);\n }\n\n if (config?.vars && config.url) {\n const tmpl = parseTemplate(config.url);\n config.url = tmpl.expand(config.vars || {});\n }\n\n // Simulate methods\n if (config.methodSimulate) {\n if (config.methodSimulateByHeader) {\n config.headers['X-HTTP-Method-Override'] = config;\n } else if (typeof config.data === 'object') {\n config.data['_method'] = config.method;\n } else if (typeof config.data === 'string') {\n if (config.data.includes('?')) {\n config.data += '&_method=' + config.method;\n } else {\n config.data += '?_method=' + config.method;\n }\n }\n\n if (config.method?.toLowerCase() !== 'get') {\n config.method = 'POST';\n }\n }\n\n return config;\n });\n\n return axios;\n}\n\nexport type UnicornHttpClient = ReturnType<typeof createHttpClient>;\n\nexport function createHttpClient(config?: CreateAxiosDefaults | AxiosInstance) {\n const axios = config && 'interceptors' in config\n ? config\n : AxiosStatic.create(config ?? {});\n\n prepareAxios(axios);\n\n function requestMiddleware(callback: Parameters<AxiosInstance['interceptors']['request']['use']>[0]) {\n return axios.interceptors.request.use(callback);\n }\n\n function responseMiddleware(callback: Parameters<AxiosInstance['interceptors']['response']['use']>[0]) {\n return axios.interceptors.response.use(callback);\n }\n\n /**\n * Send a GET request.\n */\n async function get<T = any, D = any>(\n url: string,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'GET';\n\n return request(options);\n }\n\n /**\n * Send a POST request.\n */\n async function post<T = any, D = any>(\n url: string,\n data?: any,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'POST';\n options.data = data;\n\n return request(options);\n }\n\n /**\n * Send a PUT request.\n *\n * @param {string} url\n * @param {any} data\n * @param {AxiosRequestConfig} options\n *\n * @returns {Promise<AxiosResponse>}\n */\n async function put<T = any, D = any>(\n url: string,\n data?: any,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'PUT';\n options.data = data;\n\n return request(options);\n }\n\n /**\n * Send a PATCH request.\n *\n * @param {string} url\n * @param {any} data\n * @param {AxiosRequestConfig} options\n *\n * @returns {Promise<AxiosResponse>}\n */\n async function patch<T = any, D = any>(\n url: string,\n data?: any,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'PATCH';\n options.data = data;\n\n return request(options);\n }\n\n /**\n * Send a DELETE request.\n *\n * @param {string} url\n * @param {any} data\n * @param {AxiosRequestConfig} options\n *\n * @returns {Promise<AxiosResponse>}\n */\n async function deletes<T = any, D = any>(\n url: string,\n data?: any,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'DELETE';\n options.data = data;\n\n return request(options);\n }\n\n /**\n * Send a HEAD request.\n *\n * @param {string} url\n * @param {AxiosRequestConfig} options\n *\n * @returns {Promise<AxiosResponse>}\n */\n async function head<T = any, D = any>(\n url: string,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'HEAD';\n\n return request(options);\n }\n\n /**\n * Send a OPTIONS request.\n *\n * @param {string} url\n * @param {AxiosRequestConfig} options\n *\n * @returns {Promise<AxiosResponse>}\n */\n async function options<T = any, D = any>(\n url: string,\n options: Partial<AxiosRequestConfig> = {}\n ): Promise<AxiosResponse<T, D>> {\n options.url = url;\n options.method = 'OPTIONS';\n\n return request(options);\n }\n\n /**\n * Send request.\n */\n async function request<T = any, D = any>(options: AxiosRequestConfig): Promise<AxiosResponse<T, D>> {\n try {\n return await axios(options);\n } catch (e) {\n (e as any).originMessage = (e as Error).message;\n\n const err = e as AxiosError<any>;\n\n if (err.response?.data?.message) {\n err.message = err.response.data.message;\n }\n\n throw err;\n }\n }\n\n return {\n axios,\n request,\n get,\n post,\n put,\n patch,\n delete: deletes,\n head,\n options,\n requestMiddleware,\n responseMiddleware,\n isCancel,\n AxiosError,\n isAxiosError,\n };\n}\n\nexport interface UnicornHttpModule {\n UnicornHttpClient: UnicornHttpClient;\n createHttpClient: typeof createHttpClient;\n}\n"],"names":["value","options","data"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- {"version":3,"file":"iframe-modal.js","sources":["../../src/module/iframe-modal.ts"],"sourcesContent":["import { Modal } from 'bootstrap';\r\nimport { useUniDirective } from '../composable';\r\nimport { mergeDeep } from '../utilities';\r\n\r\ninterface IFrameModalOptions {\r\n id?: string;\r\n size?: string;\r\n resize?: boolean;\r\n height?: string;\r\n}\r\n\r\nexport class IFrameModalElement extends HTMLElement {\r\n static is = 'uni-iframe-modal';\r\n\r\n options!: IFrameModalOptions;\r\n modalElement!: HTMLDivElement;\r\n modal!: Modal;\r\n iframe!: HTMLIFrameElement;\r\n\r\n template() {\r\n return `\r\n<div class=\"modal fade c-unicorn-iframe-modal\" id=\"${this.getModalId()}\"\r\n data-iframe-modal>\r\n <div class=\"modal-dialog ${this.options?.size || 'modal-xl'}\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-body\">\r\n <iframe class=\"c-unicorn-iframe-modal__iframe\" width=\"100%\" src=\"\" frameborder=\"0\"></iframe>\r\n </div>\r\n </div>\r\n </div>\r\n</div>`;\r\n }\r\n\r\n get selector() {\r\n return this.getAttribute('selector') || '[data-iframe-modal]';\r\n }\r\n\r\n async getBootstrapModal() {\r\n const { Modal } = await import('bootstrap');\r\n\r\n return this.modal ??= Modal.getOrCreateInstance(this.modalElement);\r\n }\r\n\r\n connectedCallback() {\r\n this.options = JSON.parse(this.getAttribute('options') || '{}');\r\n\r\n if (!this.innerHTML.trim()) {\r\n this.innerHTML = this.template();\r\n }\r\n\r\n this.modalElement = this.querySelector<HTMLDivElement>(this.selector)!;\r\n this.iframe = this.modalElement.querySelector<HTMLIFrameElement>('iframe')!;\r\n\r\n // @ts-ignore\r\n this.iframe.modalLink = () => {\r\n return this;\r\n };\r\n\r\n this.bindEvents();\r\n this.getBootstrapModal();\r\n }\r\n\r\n bindEvents() {\r\n this.modalElement.addEventListener('hidden.bs.modal', () => {\r\n this.iframe.src = '';\r\n });\r\n }\r\n\r\n async open(href: string, options: IFrameModalOptions = {}) {\r\n options = mergeDeep(\r\n {\r\n height: undefined,\r\n resize: false,\r\n size: 'modal-lg',\r\n },\r\n this.options,\r\n options\r\n );\r\n\r\n if (options.resize) {\r\n const onload = () => {\r\n this.resize(this.iframe);\r\n\r\n this.iframe.removeEventListener('load', onload);\r\n };\r\n\r\n this.iframe.addEventListener('load', onload);\r\n } else {\r\n this.iframe.style.height = options.height || '500px';\r\n }\r\n\r\n if (options.size != null) {\r\n const dialog = this.modalElement.querySelector<HTMLDivElement>('.modal-dialog')!;\r\n dialog.classList.remove('modal-lg', 'modal-xl', 'modal-sm', 'modal-xs');\r\n dialog.classList.add(options.size);\r\n }\r\n\r\n this.iframe.src = href;\r\n const modal = await this.getBootstrapModal();\r\n modal.show();\r\n }\r\n\r\n async close() {\r\n this.iframe.src = '';\r\n const modal = await this.getBootstrapModal();\r\n modal.hide();\r\n }\r\n\r\n resize(iframe: HTMLIFrameElement) {\r\n setTimeout(() => {\r\n if (!iframe.contentWindow) {\r\n return;\r\n }\r\n\r\n let height = iframe.contentWindow.document.documentElement.scrollHeight;\r\n\r\n height += 30;\r\n\r\n if (height < 500) {\r\n height = 500;\r\n }\r\n\r\n iframe.style.height = height + 'px';\r\n }, 30);\r\n }\r\n\r\n getModalId() {\r\n return this.options?.id || this.id + '__modal';\r\n }\r\n}\r\n\r\nasync function init() {\r\n customElements.define(IFrameModalElement.is, IFrameModalElement);\r\n\r\n return useUniDirective('modal-link', {\r\n mounted(el, binding) {\r\n let options: IFrameModalOptions = {};\r\n\r\n options.height = el.dataset.height;\r\n options.resize = el.dataset.resize === '1' || el.dataset.resize === 'true';\r\n options.size = el.dataset.size;\r\n\r\n const target = binding.value;\r\n\r\n el.style.pointerEvents = '';\r\n\r\n el.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const im = document.querySelector(target);\r\n\r\n if (!im) {\r\n return;\r\n }\r\n\r\n if ('src' in el) {\r\n im.open(el.src, options);\r\n } else if ('href' in el) {\r\n im.open(el.href, options);\r\n }\r\n });\r\n }\r\n });\r\n}\r\nexport const ready = init();\r\n\r\nexport interface IFrameModalModule {\r\n IFrameModalElement: typeof IFrameModalElement;\r\n ready: typeof ready;\r\n}\r\n"],"names":["Modal"],"mappings":"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"}
1
+ {"version":3,"file":"iframe-modal.js","sources":["../../src/module/iframe-modal.ts"],"sourcesContent":["import { Modal } from 'bootstrap';\nimport { useUniDirective } from '../composable';\nimport { mergeDeep } from '../utilities';\n\ninterface IFrameModalOptions {\n id?: string;\n size?: string;\n resize?: boolean;\n height?: string;\n}\n\nexport class IFrameModalElement extends HTMLElement {\n static is = 'uni-iframe-modal';\n\n options!: IFrameModalOptions;\n modalElement!: HTMLDivElement;\n modal!: Modal;\n iframe!: HTMLIFrameElement;\n\n template() {\n return `\n<div class=\"modal fade c-unicorn-iframe-modal\" id=\"${this.getModalId()}\"\n data-iframe-modal>\n <div class=\"modal-dialog ${this.options?.size || 'modal-xl'}\">\n <div class=\"modal-content\">\n <div class=\"modal-body\">\n <iframe class=\"c-unicorn-iframe-modal__iframe\" width=\"100%\" src=\"\" frameborder=\"0\"></iframe>\n </div>\n </div>\n </div>\n</div>`;\n }\n\n get selector() {\n return this.getAttribute('selector') || '[data-iframe-modal]';\n }\n\n async getBootstrapModal() {\n const { Modal } = await import('bootstrap');\n\n return this.modal ??= Modal.getOrCreateInstance(this.modalElement);\n }\n\n connectedCallback() {\n this.options = JSON.parse(this.getAttribute('options') || '{}');\n\n if (!this.innerHTML.trim()) {\n this.innerHTML = this.template();\n }\n\n this.modalElement = this.querySelector<HTMLDivElement>(this.selector)!;\n this.iframe = this.modalElement.querySelector<HTMLIFrameElement>('iframe')!;\n\n // @ts-ignore\n this.iframe.modalLink = () => {\n return this;\n };\n\n this.bindEvents();\n this.getBootstrapModal();\n }\n\n bindEvents() {\n this.modalElement.addEventListener('hidden.bs.modal', () => {\n this.iframe.src = '';\n });\n }\n\n async open(href: string, options: IFrameModalOptions = {}) {\n options = mergeDeep(\n {\n height: undefined,\n resize: false,\n size: 'modal-lg',\n },\n this.options,\n options\n );\n\n if (options.resize) {\n const onload = () => {\n this.resize(this.iframe);\n\n this.iframe.removeEventListener('load', onload);\n };\n\n this.iframe.addEventListener('load', onload);\n } else {\n this.iframe.style.height = options.height || '500px';\n }\n\n if (options.size != null) {\n const dialog = this.modalElement.querySelector<HTMLDivElement>('.modal-dialog')!;\n dialog.classList.remove('modal-lg', 'modal-xl', 'modal-sm', 'modal-xs');\n dialog.classList.add(options.size);\n }\n\n this.iframe.src = href;\n const modal = await this.getBootstrapModal();\n modal.show();\n }\n\n async close() {\n this.iframe.src = '';\n const modal = await this.getBootstrapModal();\n modal.hide();\n }\n\n resize(iframe: HTMLIFrameElement) {\n setTimeout(() => {\n if (!iframe.contentWindow) {\n return;\n }\n\n let height = iframe.contentWindow.document.documentElement.scrollHeight;\n\n height += 30;\n\n if (height < 500) {\n height = 500;\n }\n\n iframe.style.height = height + 'px';\n }, 30);\n }\n\n getModalId() {\n return this.options?.id || this.id + '__modal';\n }\n}\n\nasync function init() {\n customElements.define(IFrameModalElement.is, IFrameModalElement);\n\n return useUniDirective('modal-link', {\n mounted(el, binding) {\n let options: IFrameModalOptions = {};\n\n options.height = el.dataset.height;\n options.resize = el.dataset.resize === '1' || el.dataset.resize === 'true';\n options.size = el.dataset.size;\n\n const target = binding.value;\n\n el.style.pointerEvents = '';\n\n el.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const im = document.querySelector(target);\n\n if (!im) {\n return;\n }\n\n if ('src' in el) {\n im.open(el.src, options);\n } else if ('href' in el) {\n im.open(el.href, options);\n }\n });\n }\n });\n}\nexport const ready = init();\n\nexport interface IFrameModalModule {\n IFrameModalElement: typeof IFrameModalElement;\n ready: typeof ready;\n}\n"],"names":["Modal"],"mappings":";AAWO,MAAM,2BAA2B,YAAY;AAAA,EAClD,OAAO,KAAK;AAAA,EAEZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,WAAW;AACT,WAAO;AAAA,qDAC0C,KAAK,YAAY;AAAA;AAAA,+BAEvC,KAAK,SAAS,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7D;AAAA,EAEA,IAAI,WAAW;AACb,WAAO,KAAK,aAAa,UAAU,KAAK;AAAA,EAC1C;AAAA,EAEA,MAAM,oBAAoB;AACxB,UAAM,EAAE,OAAAA,WAAU,MAAM,OAAO,WAAW;AAE1C,WAAO,KAAK,UAAUA,OAAM,oBAAoB,KAAK,YAAY;AAAA,EACnE;AAAA,EAEA,oBAAoB;AAClB,SAAK,UAAU,KAAK,MAAM,KAAK,aAAa,SAAS,KAAK,IAAI;AAE9D,QAAI,CAAC,KAAK,UAAU,QAAQ;AAC1B,WAAK,YAAY,KAAK,SAAA;AAAA,IACxB;AAEA,SAAK,eAAe,KAAK,cAA8B,KAAK,QAAQ;AACpE,SAAK,SAAS,KAAK,aAAa,cAAiC,QAAQ;AAGzE,SAAK,OAAO,YAAY,MAAM;AAC5B,aAAO;AAAA,IACT;AAEA,SAAK,WAAA;AACL,SAAK,kBAAA;AAAA,EACP;AAAA,EAEA,aAAa;AACX,SAAK,aAAa,iBAAiB,mBAAmB,MAAM;AAC1D,WAAK,OAAO,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KAAK,MAAc,UAA8B,IAAI;AACzD,cAAU;AAAA,MACR;AAAA,QACE,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,MAAM;AAAA,MAAA;AAAA,MAER,KAAK;AAAA,MACL;AAAA,IAAA;AAGF,QAAI,QAAQ,QAAQ;AAClB,YAAM,SAAS,MAAM;AACnB,aAAK,OAAO,KAAK,MAAM;AAEvB,aAAK,OAAO,oBAAoB,QAAQ,MAAM;AAAA,MAChD;AAEA,WAAK,OAAO,iBAAiB,QAAQ,MAAM;AAAA,IAC7C,OAAO;AACL,WAAK,OAAO,MAAM,SAAS,QAAQ,UAAU;AAAA,IAC/C;AAEA,QAAI,QAAQ,QAAQ,MAAM;AACxB,YAAM,SAAS,KAAK,aAAa,cAA8B,eAAe;AAC9E,aAAO,UAAU,OAAO,YAAY,YAAY,YAAY,UAAU;AACtE,aAAO,UAAU,IAAI,QAAQ,IAAI;AAAA,IACnC;AAEA,SAAK,OAAO,MAAM;AAClB,UAAM,QAAQ,MAAM,KAAK,kBAAA;AACzB,UAAM,KAAA;AAAA,EACR;AAAA,EAEA,MAAM,QAAQ;AACZ,SAAK,OAAO,MAAM;AAClB,UAAM,QAAQ,MAAM,KAAK,kBAAA;AACzB,UAAM,KAAA;AAAA,EACR;AAAA,EAEA,OAAO,QAA2B;AAChC,eAAW,MAAM;AACf,UAAI,CAAC,OAAO,eAAe;AACzB;AAAA,MACF;AAEA,UAAI,SAAS,OAAO,cAAc,SAAS,gBAAgB;AAE3D,gBAAU;AAEV,UAAI,SAAS,KAAK;AAChB,iBAAS;AAAA,MACX;AAEA,aAAO,MAAM,SAAS,SAAS;AAAA,IACjC,GAAG,EAAE;AAAA,EACP;AAAA,EAEA,aAAa;AACX,WAAO,KAAK,SAAS,MAAM,KAAK,KAAK;AAAA,EACvC;AACF;AAEA,eAAe,OAAO;AACpB,iBAAe,OAAO,mBAAmB,IAAI,kBAAkB;AAE/D,SAAO,gBAAgB,cAAc;AAAA,IACnC,QAAQ,IAAI,SAAS;AACnB,UAAI,UAA8B,CAAA;AAElC,cAAQ,SAAS,GAAG,QAAQ;AAC5B,cAAQ,SAAS,GAAG,QAAQ,WAAW,OAAO,GAAG,QAAQ,WAAW;AACpE,cAAQ,OAAO,GAAG,QAAQ;AAE1B,YAAM,SAAS,QAAQ;AAEvB,SAAG,MAAM,gBAAgB;AAEzB,SAAG,iBAAiB,SAAS,CAAC,MAAM;AAClC,UAAE,eAAA;AACF,UAAE,gBAAA;AACF,cAAM,KAAK,SAAS,cAAc,MAAM;AAExC,YAAI,CAAC,IAAI;AACP;AAAA,QACF;AAEA,YAAI,SAAS,IAAI;AACf,aAAG,KAAK,GAAG,KAAK,OAAO;AAAA,QACzB,WAAW,UAAU,IAAI;AACvB,aAAG,KAAK,GAAG,MAAM,OAAO;AAAA,QAC1B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EAAA,CACD;AACH;AACO,MAAM,QAAQ,qBAAA;"}
@@ -1 +1 @@
1
- {"version":3,"file":"keep-tab.js","sources":["../../src/bootstrap/keep-tab.ts"],"sourcesContent":["import { useUniDirective } from '../composable';\r\nimport { module, selectAll, selectOne, sleep } from '../service';\r\nimport { Tab } from 'bootstrap';\r\nimport { mergeDeep } from '../utilities';\r\n\r\nexport interface KeepTabOptions {\r\n uid?: string;\r\n delay?: number;\r\n tabItemSelector?: string;\r\n}\r\n\r\nconst defaultOptions = {\r\n tabItemSelector: '[data-toggle=tab],[data-bs-toggle=tab],[data-toggle=pill],[data-bs-toggle=pill]',\r\n delay: 0,\r\n};\r\n\r\nexport class KeepTab {\r\n $element: HTMLElement;\r\n tabButtons!: NodeListOf<HTMLElement>;\r\n storageKey: string = '';\r\n options: any;\r\n\r\n constructor(selector: HTMLElement | string, options: KeepTabOptions = {}) {\r\n options = mergeDeep({}, defaultOptions, options);\r\n let uid: string;\r\n\r\n if (typeof selector === 'object') {\r\n uid = options.uid || selector.id;\r\n } else {\r\n uid = selector;\r\n }\r\n\r\n const $element = this.$element = selectOne<HTMLElement>(selector)!;\r\n\r\n if (!$element) {\r\n console.warn(`[KeepTab] Element ${selector} not found.`);\r\n return;\r\n }\r\n\r\n this.options = options;\r\n\r\n this.$element = $element;\r\n this.tabButtons = $element.querySelectorAll(this.options.tabItemSelector);\r\n\r\n this.init(uid);\r\n }\r\n\r\n protected async init(uid: string) {\r\n this.storageKey = 'tab-href-' + await this.hashCode(location.href + ':' + uid);\r\n\r\n this.bindEvents();\r\n\r\n await sleep(this.options.delay || 0);\r\n\r\n this.switchTab();\r\n }\r\n\r\n bindEvents() {\r\n [].forEach.call(this.tabButtons, (button: HTMLAnchorElement) => {\r\n button.addEventListener('click', () => {\r\n // Store the selected tab href in localstorage\r\n window.localStorage.setItem(this.storageKey, this.getButtonHref(button));\r\n });\r\n });\r\n }\r\n\r\n getButtonHref(button: HTMLAnchorElement) {\r\n return button.dataset.bsTarget || button.dataset.target || button.href;\r\n }\r\n\r\n findTabButtonByHref(href: string) {\r\n return selectAll<HTMLAnchorElement>(this.options.tabItemSelector)\r\n .filter((button: HTMLAnchorElement) => {\r\n if (button.href === href) {\r\n return true;\r\n }\r\n\r\n if (button.dataset.bsTarget === href) {\r\n return true;\r\n }\r\n\r\n return button.dataset.target === href;\r\n })\r\n .shift();\r\n }\r\n\r\n activateTab(href: string) {\r\n const tabTrigger = this.findTabButtonByHref(href);\r\n\r\n if (tabTrigger) {\r\n Tab.getOrCreateInstance(tabTrigger).show();\r\n }\r\n }\r\n\r\n hasTab(href: string) {\r\n return this.findTabButtonByHref(href) != null;\r\n }\r\n\r\n /**\r\n * Switch tab.\r\n *\r\n * @returns {boolean}\r\n */\r\n switchTab() {\r\n if (localStorage.getItem(this.storageKey)) {\r\n // When moving from tab area to a different view\r\n if (!this.hasTab(localStorage.getItem(this.storageKey) || '')) {\r\n localStorage.removeItem(this.storageKey);\r\n return true;\r\n }\r\n\r\n // Clean default tabs\r\n // selectOne(this.$element, '[data-toggle=\"tab\"], [data-bs-toggle=tab]')\r\n // this.$element.querySelector('a[data-toggle=\"tab\"]').parent().removeClass('active');\r\n\r\n const tabhref = localStorage.getItem(this.storageKey) || '';\r\n\r\n // Add active attribute for selected tab indicated by url\r\n this.activateTab(tabhref);\r\n\r\n // Check whether internal tab is selected (in format <tabname>-<id>)\r\n // const seperatorIndex = tabhref.indexOf('-');\r\n //\r\n // if (seperatorIndex !== -1) {\r\n // const singular = tabhref.substring(0, seperatorIndex);\r\n // const plural = singular + 's';\r\n //\r\n // this.activateTab(plural);\r\n // }\r\n }\r\n }\r\n\r\n /**\r\n * Hash code.\r\n */\r\n async hashCode(text: string): Promise<string> {\r\n const msgBuffer = new TextEncoder().encode(text);\r\n const hashBuffer = await globalThis.crypto.subtle.digest(\"SHA-256\", msgBuffer);\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n return hashArray.map(b => b.toString(16).padStart(2, \"0\")).join(\"\");\r\n }\r\n}\r\n\r\nexport const ready = useUniDirective('keeptab', {\r\n mounted(el, { value }) {\r\n const options: KeepTabOptions = JSON.parse(value || '{}');\r\n\r\n module(el, 'uni.keeptab', () => new KeepTab(el, options));\r\n }\r\n});\r\n\r\nexport interface KeepTabModule {\r\n KeepTab: typeof KeepTab;\r\n ready: typeof ready;\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keep-tab.js","sources":["../../src/bootstrap/keep-tab.ts"],"sourcesContent":["import { useUniDirective } from '../composable';\nimport { module, selectAll, selectOne, sleep } from '../service';\nimport { Tab } from 'bootstrap';\nimport { mergeDeep } from '../utilities';\n\nexport interface KeepTabOptions {\n uid?: string;\n delay?: number;\n tabItemSelector?: string;\n}\n\nconst defaultOptions = {\n tabItemSelector: '[data-toggle=tab],[data-bs-toggle=tab],[data-toggle=pill],[data-bs-toggle=pill]',\n delay: 0,\n};\n\nexport class KeepTab {\n $element: HTMLElement;\n tabButtons!: NodeListOf<HTMLElement>;\n storageKey: string = '';\n options: any;\n\n constructor(selector: HTMLElement | string, options: KeepTabOptions = {}) {\n options = mergeDeep({}, defaultOptions, options);\n let uid: string;\n\n if (typeof selector === 'object') {\n uid = options.uid || selector.id;\n } else {\n uid = selector;\n }\n\n const $element = this.$element = selectOne<HTMLElement>(selector)!;\n\n if (!$element) {\n console.warn(`[KeepTab] Element ${selector} not found.`);\n return;\n }\n\n this.options = options;\n\n this.$element = $element;\n this.tabButtons = $element.querySelectorAll(this.options.tabItemSelector);\n\n this.init(uid);\n }\n\n protected async init(uid: string) {\n this.storageKey = 'tab-href-' + await this.hashCode(location.href + ':' + uid);\n\n this.bindEvents();\n\n await sleep(this.options.delay || 0);\n\n this.switchTab();\n }\n\n bindEvents() {\n [].forEach.call(this.tabButtons, (button: HTMLAnchorElement) => {\n button.addEventListener('click', () => {\n // Store the selected tab href in localstorage\n window.localStorage.setItem(this.storageKey, this.getButtonHref(button));\n });\n });\n }\n\n getButtonHref(button: HTMLAnchorElement) {\n return button.dataset.bsTarget || button.dataset.target || button.href;\n }\n\n findTabButtonByHref(href: string) {\n return selectAll<HTMLAnchorElement>(this.options.tabItemSelector)\n .filter((button: HTMLAnchorElement) => {\n if (button.href === href) {\n return true;\n }\n\n if (button.dataset.bsTarget === href) {\n return true;\n }\n\n return button.dataset.target === href;\n })\n .shift();\n }\n\n activateTab(href: string) {\n const tabTrigger = this.findTabButtonByHref(href);\n\n if (tabTrigger) {\n Tab.getOrCreateInstance(tabTrigger).show();\n }\n }\n\n hasTab(href: string) {\n return this.findTabButtonByHref(href) != null;\n }\n\n /**\n * Switch tab.\n *\n * @returns {boolean}\n */\n switchTab() {\n if (localStorage.getItem(this.storageKey)) {\n // When moving from tab area to a different view\n if (!this.hasTab(localStorage.getItem(this.storageKey) || '')) {\n localStorage.removeItem(this.storageKey);\n return true;\n }\n\n // Clean default tabs\n // selectOne(this.$element, '[data-toggle=\"tab\"], [data-bs-toggle=tab]')\n // this.$element.querySelector('a[data-toggle=\"tab\"]').parent().removeClass('active');\n\n const tabhref = localStorage.getItem(this.storageKey) || '';\n\n // Add active attribute for selected tab indicated by url\n this.activateTab(tabhref);\n\n // Check whether internal tab is selected (in format <tabname>-<id>)\n // const seperatorIndex = tabhref.indexOf('-');\n //\n // if (seperatorIndex !== -1) {\n // const singular = tabhref.substring(0, seperatorIndex);\n // const plural = singular + 's';\n //\n // this.activateTab(plural);\n // }\n }\n }\n\n /**\n * Hash code.\n */\n async hashCode(text: string): Promise<string> {\n const msgBuffer = new TextEncoder().encode(text);\n const hashBuffer = await globalThis.crypto.subtle.digest(\"SHA-256\", msgBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n}\n\nexport const ready = useUniDirective('keeptab', {\n mounted(el, { value }) {\n const options: KeepTabOptions = JSON.parse(value || '{}');\n\n module(el, 'uni.keeptab', () => new KeepTab(el, options));\n }\n});\n\nexport interface KeepTabModule {\n KeepTab: typeof KeepTab;\n ready: typeof ready;\n}\n"],"names":[],"mappings":"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"}