@leaflink/stash 44.6.0 → 44.6.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"FileUpload.js","sources":["../src/components/FileUpload/FileUpload.constants.ts","../src/components/FileUpload/FileUpload.vue"],"sourcesContent":["export const FILE_TYPES = {\n CSV: {\n EXTENSION: ['csv'],\n MIME_TYPES: ['text/csv', 'application/octet-stream', 'application/vnd.ms-excel'],\n ILLUSTRATION: 'csv',\n },\n PDF: {\n EXTENSION: ['pdf'],\n MIME_TYPES: ['application/pdf'],\n ILLUSTRATION: 'pdf',\n },\n PNG: {\n EXTENSION: ['png'],\n MIME_TYPES: ['image/png'],\n ILLUSTRATION: 'image',\n },\n JPEG: {\n EXTENSION: ['jpg', 'jpeg'],\n MIME_TYPES: ['image/jpeg'],\n ILLUSTRATION: 'image',\n },\n DOC: {\n EXTENSION: ['doc', 'docx'],\n MIME_TYPES: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],\n ILLUSTRATION: 'document',\n },\n XLS: {\n EXTENSION: ['xls', 'xlsx'],\n MIME_TYPES: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\n ILLUSTRATION: 'csv',\n },\n};\n\nexport enum FileUploadSizes {\n Dense = 'dense',\n Standard = 'standard',\n}\n\nexport type FileUploadSize = `${FileUploadSizes}`;\n","<script lang=\"ts\">\n export * from './FileUpload.constants';\n</script>\n\n<script setup lang=\"ts\">\n import logger from '@leaflink/snitch';\n import { computed, inject, ref, useAttrs, useCssModule } from 'vue';\n import InlineSvg from 'vue-inline-svg';\n\n import { StashProvideState } from '../../../types/misc';\n import { t } from '../../locale';\n import Button from '../Button/Button.vue';\n import Icon from '../Icon/Icon.vue';\n import { FILE_TYPES, FileUploadSize, FileUploadSizes } from './FileUpload.constants';\n\n export type FileType = 'CSV' | 'PDF' | 'PNG' | 'JPEG' | 'DOC' | 'XLS';\n\n export interface FileUploadProps {\n /**\n * Files to display in the component\n */\n files?: File[];\n\n /**\n * Accepted file types\n */\n fileTypes?: FileType[];\n\n /**\n * Should display only the button\n */\n buttonOnly?: boolean;\n\n /**\n * Allows upload of multiple files\n */\n multiple?: boolean;\n\n /**\n * Is the input disabled\n */\n disabled?: boolean;\n\n /**\n * Component size\n */\n size?: FileUploadSize;\n }\n\n const props = withDefaults(defineProps<FileUploadProps>(), {\n files: () => [],\n fileTypes: () => ['CSV', 'PDF', 'PNG', 'JPEG', 'DOC', 'XLS'],\n buttonOnly: false,\n disabled: false,\n multiple: false,\n size: 'standard',\n });\n\n const classes = useCssModule();\n\n const emit =\n defineEmits<{\n (e: 'file-select', { files }: { files: FileUploadProps['files'] }): void;\n (e: 'file-delete', file: File): void;\n (e: 'file-error', message: string): void;\n }>();\n\n const isDraggingOver = ref(false);\n const fileUploadRef = ref<HTMLInputElement>();\n\n const stashOptions = inject<StashProvideState>('stashOptions');\n const attributes = useAttrs();\n\n const inputAttrs = computed(() => {\n const attrs = { ...attributes };\n\n delete attrs['data-test'];\n delete attrs.class;\n delete attrs.type;\n delete attrs.accept;\n\n return attrs;\n });\n\n function concatArraysToFirst(a: any[], b: any[]) {\n return a.concat(b);\n }\n\n const acceptedMimeTypes = computed(() => {\n return props.fileTypes.map((fileType) => FILE_TYPES[fileType].MIME_TYPES).reduce(concatArraysToFirst);\n });\n\n const acceptedFileExtensions = computed(() => {\n return props.fileTypes.map((fileType) => FILE_TYPES[fileType].EXTENSION).reduce(concatArraysToFirst);\n });\n\n const illustrationPath = computed(() => {\n return `${stashOptions?.staticPath}/illustrations/FileUpload/${FILE_TYPES[props.fileTypes[0]].ILLUSTRATION}.svg`;\n });\n\n function openFileDialog() {\n if (fileUploadRef.value) {\n fileUploadRef.value.value = '';\n fileUploadRef.value.click();\n }\n }\n\n function handleDragEnter() {\n isDraggingOver.value = true;\n }\n\n function handleDragLeave() {\n isDraggingOver.value = false;\n }\n\n function handleFileError(error: Error) {\n const message = t('ll.fileUpload.errors.incorrectFileType', {\n fileTypes: acceptedFileExtensions.value.join(', '),\n });\n\n emit('file-error', message);\n\n logger.log(error);\n }\n\n async function areFileTypesAccepted(files: File[]) {\n if (!acceptedMimeTypes.value.length) return true;\n\n const mimeTypes = await Promise.all(files.map((file) => readMimeType(file)));\n\n const allCorrectMimeTypes =\n !!mimeTypes.length && mimeTypes.every((mimeType) => acceptedMimeTypes.value.includes(mimeType));\n\n if (!allCorrectMimeTypes) {\n throw new Error('One or more files contains an unacceptable mime type.');\n }\n\n const allCorrectFileExtensions = files.every((file) => {\n const extension = file.name.split('.').pop();\n\n return extension && acceptedFileExtensions.value.includes(extension);\n });\n\n if (!allCorrectFileExtensions) {\n throw new Error('One or more files contains an unacceptable extension.');\n }\n\n return true;\n }\n\n async function processFiles(files: File[]) {\n try {\n await areFileTypesAccepted(files);\n\n emit('file-select', { files });\n } catch (error) {\n handleFileError(error as Error);\n }\n }\n\n /**\n * Sets file(s) to selected file(s) from dialogue\n * @param {Object} event - file select event that contains file(s)\n * @returns {Array} An array of files\n */\n function handleFileInput(event: Event) {\n const files = [...((event.target as HTMLInputElement)?.files || [])];\n\n processFiles(files);\n }\n\n /**\n * Sets file to dropped file if it is proper file type\n * @param {Object} event - file select event that contains file\n */\n function handleDropFile(event: DragEvent) {\n if (props.disabled) {\n return;\n }\n\n const files = [...(event.dataTransfer?.files || [])];\n\n isDraggingOver.value = false;\n\n return processFiles(files);\n }\n\n function handleFileDelete(file: File) {\n emit('file-delete', file);\n }\n\n function readMimeType(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n if (file.type) {\n return resolve(file.type);\n } else if (window.FileReader) {\n const fileReader = new FileReader();\n\n fileReader.onload = () => {\n const mimeType =\n fileReader.result && (fileReader.result as string).match(/[^:]\\w+\\/[\\w-+\\d.]+(?=;|,)/)\n ? ((fileReader.result as string).match(/[^:]\\w+\\/[\\w-+\\d.]+(?=;|,)/) as string[])[0]\n : '';\n\n resolve(mimeType);\n };\n\n fileReader.readAsDataURL(file);\n } else {\n reject(new Error('Failed to read file.'));\n }\n });\n }\n</script>\n\n<template>\n <div class=\"stash-file-upload\" :class=\"attributes.class\" data-test=\"stash-file-upload\">\n <div v-if=\"buttonOnly\">\n <Button secondary type=\"button\" :disabled=\"disabled || null\" @click.stop.prevent=\"openFileDialog\">\n <slot name=\"submitText\">\n {{ t('ll.fileUpload.uploadFile') }}\n </slot>\n </Button>\n </div>\n <div\n v-else\n class=\"tw-rounded tw-p-6\"\n :class=\"[classes['file-dropbox'], isDraggingOver && classes['is-dragging'], disabled && classes['is-disabled']]\"\n @dragover.prevent=\"handleDragEnter\"\n @drop.prevent=\"handleDropFile\"\n @dragleave.prevent=\"handleDragLeave\"\n >\n <div\n class=\"tw-flex tw-flex-col tw-items-center tw-justify-center tw-text-center\"\n :class=\"[{ 'tw-items-center md:tw-flex-row': size === FileUploadSizes.Dense }]\"\n >\n <template v-if=\"!files.length\">\n <InlineSvg v-if=\"size !== FileUploadSizes.Dense\" :src=\"illustrationPath\" name=\"file\" width=\"84\" height=\"96\" />\n <span class=\"tw-text-ice-900\">\n {{ t('ll.fileUpload.dragDropFileHere') }}\n </span>\n <span\n :class=\"\n size === FileUploadSizes.Dense\n ? 'md:tw-ml-1.5 md:tw-mr-3 md:tw-my-0 tw-my-1.5 tw-text-ice-900'\n : 'tw-mt-1.5 tw-my-1.5'\n \"\n >\n {{ t('ll.fileUpload.or') }}\n </span>\n <Button\n class=\"tw-mt-1.5\"\n secondary\n type=\"button\"\n :class=\"classes['file-select-button']\"\n :disabled=\"disabled\"\n @click.stop.prevent=\"openFileDialog\"\n >\n <!-- @slot for custom submit text -->\n <slot name=\"submitText\">{{ t('ll.fileUpload.uploadFile') }}</slot>\n </Button>\n </template>\n <template v-else>\n <div v-for=\"file in files\" :key=\"file.name\">\n <Icon name=\"file\" />\n <span>{{ file.name }}</span>\n <Button :class=\"[classes['remove-button'], classes['button']]\" @click.stop.prevent=\"handleFileDelete(file)\">\n {{ t('ll.fileUpload.remove') }}\n </Button>\n </div>\n </template>\n </div>\n <div v-if=\"$slots.hint && !files.length\" class=\"tw-mt-6 tw-text-center tw-text-xs tw-text-ice-700\">\n <!-- @slot for displaying helpful text and/or links -->\n <slot name=\"hint\"></slot>\n </div>\n </div>\n <input\n v-show=\"false\"\n v-bind=\"inputAttrs\"\n ref=\"fileUploadRef\"\n data-test=\"stash-file-upload|input\"\n type=\"file\"\n :disabled=\"disabled\"\n :accept=\"acceptedMimeTypes.join(',')\"\n :multiple=\"props.multiple\"\n @change=\"handleFileInput\"\n />\n </div>\n</template>\n\n<style module>\n .file-dropbox {\n background: var(--color-ice-200);\n background-image: url(\"data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='4' ry='4' stroke='%23C5C9D4FF' stroke-width='1' stroke-dasharray='5 %2c 5' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e\");\n background-repeat: no-repeat;\n border: theme('borderWidth.DEFAULT') solid var(--color-ice-500);\n border-color: transparent;\n }\n\n .is-dragging {\n background-image: none;\n border-color: var(--color-ice-500);\n\n & > * {\n pointer-events: none;\n }\n }\n\n .is-disabled {\n cursor: no-drop;\n }\n\n /* Constrain the upload icon for drag/drop to the required size */\n .upload-icon {\n height: 98px;\n width: 84px;\n }\n\n .remove-button.button {\n background: transparent;\n border: none;\n color: var(--color-red-500);\n\n &:hover {\n background: transparent;\n border: none;\n }\n }\n</style>\n"],"names":["FILE_TYPES","FileUploadSizes","classes","useCssModule","isDraggingOver","ref","fileUploadRef","stashOptions","inject","attributes","useAttrs","inputAttrs","computed","attrs","concatArraysToFirst","a","b","acceptedMimeTypes","props","fileType","acceptedFileExtensions","illustrationPath","openFileDialog","handleDragEnter","handleDragLeave","handleFileError","error","message","t","emit","logger","areFileTypesAccepted","files","mimeTypes","file","readMimeType","mimeType","extension","processFiles","handleFileInput","event","_a","handleDropFile","handleFileDelete","resolve","reject","fileReader"],"mappings":"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"}
1
+ {"version":3,"file":"FileUpload.js","sources":["../src/components/FileUpload/FileUpload.constants.ts","../src/components/FileUpload/FileUpload.vue"],"sourcesContent":["export const FILE_TYPES = {\n CSV: {\n EXTENSION: ['csv'],\n MIME_TYPES: ['text/csv', 'application/octet-stream', 'application/vnd.ms-excel'],\n ILLUSTRATION: 'csv',\n },\n PDF: {\n EXTENSION: ['pdf'],\n MIME_TYPES: ['application/pdf'],\n ILLUSTRATION: 'pdf',\n },\n PNG: {\n EXTENSION: ['png'],\n MIME_TYPES: ['image/png'],\n ILLUSTRATION: 'image',\n },\n JPEG: {\n EXTENSION: ['jpg', 'jpeg'],\n MIME_TYPES: ['image/jpeg'],\n ILLUSTRATION: 'image',\n },\n DOC: {\n EXTENSION: ['doc', 'docx'],\n MIME_TYPES: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],\n ILLUSTRATION: 'document',\n },\n XLS: {\n EXTENSION: ['xls', 'xlsx'],\n MIME_TYPES: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\n ILLUSTRATION: 'csv',\n },\n};\n\nexport enum FileUploadSizes {\n Dense = 'dense',\n Standard = 'standard',\n}\n\nexport type FileUploadSize = `${FileUploadSizes}`;\n","<script lang=\"ts\">\n export * from './FileUpload.constants';\n</script>\n\n<script setup lang=\"ts\">\n import logger from '@leaflink/snitch';\n import { computed, inject, ref, useAttrs, useCssModule } from 'vue';\n import InlineSvg from 'vue-inline-svg';\n\n import { StashProvideState } from '../../../types/misc';\n import { t } from '../../locale';\n import Button from '../Button/Button.vue';\n import Icon from '../Icon/Icon.vue';\n import { FILE_TYPES, FileUploadSize, FileUploadSizes } from './FileUpload.constants';\n\n export type FileType = 'CSV' | 'PDF' | 'PNG' | 'JPEG' | 'DOC' | 'XLS';\n\n export interface FileUploadProps {\n /**\n * Files to display in the component\n */\n files?: File[];\n\n /**\n * Accepted file types\n */\n fileTypes?: FileType[];\n\n /**\n * Should display only the button\n */\n buttonOnly?: boolean;\n\n /**\n * Allows upload of multiple files\n */\n multiple?: boolean;\n\n /**\n * Is the input disabled\n */\n disabled?: boolean;\n\n /**\n * Component size\n */\n size?: FileUploadSize;\n }\n\n const props = withDefaults(defineProps<FileUploadProps>(), {\n files: () => [],\n fileTypes: () => ['CSV', 'PDF', 'PNG', 'JPEG', 'DOC', 'XLS'],\n buttonOnly: false,\n disabled: false,\n multiple: false,\n size: 'standard',\n });\n\n const classes = useCssModule();\n\n const emit =\n defineEmits<{\n (e: 'file-select', { files }: { files: FileUploadProps['files'] }): void;\n (e: 'file-delete', file: File): void;\n (e: 'file-error', message: string): void;\n }>();\n\n const isDraggingOver = ref(false);\n const fileUploadRef = ref<HTMLInputElement>();\n\n const stashOptions = inject<StashProvideState>('stashOptions');\n const attributes = useAttrs();\n\n const inputAttrs = computed(() => {\n const attrs = { ...attributes };\n\n delete attrs['data-test'];\n delete attrs.class;\n delete attrs.type;\n delete attrs.accept;\n\n return attrs;\n });\n\n function concatArraysToFirst(a: string[], b: string[]) {\n return a.concat(b);\n }\n\n const acceptedMimeTypes = computed(() => {\n return props.fileTypes.map((fileType) => FILE_TYPES[fileType].MIME_TYPES).reduce(concatArraysToFirst);\n });\n\n const acceptedFileExtensions = computed(() => {\n return props.fileTypes.map((fileType) => FILE_TYPES[fileType].EXTENSION).reduce(concatArraysToFirst);\n });\n\n const illustrationPath = computed(() => {\n return `${stashOptions?.staticPath}/illustrations/FileUpload/${FILE_TYPES[props.fileTypes[0]].ILLUSTRATION}.svg`;\n });\n\n function openFileDialog() {\n if (fileUploadRef.value) {\n fileUploadRef.value.value = '';\n fileUploadRef.value.click();\n }\n }\n\n function handleDragEnter() {\n isDraggingOver.value = true;\n }\n\n function handleDragLeave() {\n isDraggingOver.value = false;\n }\n\n function handleFileError(error: Error) {\n const message = t('ll.fileUpload.errors.incorrectFileType', {\n fileTypes: acceptedFileExtensions.value.join(', '),\n });\n\n emit('file-error', message);\n\n logger.log(error);\n }\n\n async function areFileTypesAccepted(files: File[]) {\n if (!acceptedMimeTypes.value.length) return true;\n\n const mimeTypes = await Promise.all(files.map((file) => readMimeType(file)));\n\n const allCorrectMimeTypes =\n !!mimeTypes.length && mimeTypes.every((mimeType) => acceptedMimeTypes.value.includes(mimeType));\n\n if (!allCorrectMimeTypes) {\n throw new Error('One or more files contains an unacceptable mime type.');\n }\n\n const allCorrectFileExtensions = files.every((file) => {\n const extension = file.name.split('.').pop();\n\n return extension && acceptedFileExtensions.value.includes(extension);\n });\n\n if (!allCorrectFileExtensions) {\n throw new Error('One or more files contains an unacceptable extension.');\n }\n\n return true;\n }\n\n async function processFiles(files: File[]) {\n try {\n await areFileTypesAccepted(files);\n\n emit('file-select', { files });\n } catch (error) {\n handleFileError(error as Error);\n }\n }\n\n /**\n * Sets file(s) to selected file(s) from dialogue\n * @param {Object} event - file select event that contains file(s)\n * @returns {Array} An array of files\n */\n function handleFileInput(event: Event) {\n const files = [...((event.target as HTMLInputElement)?.files || [])];\n\n processFiles(files);\n }\n\n /**\n * Sets file to dropped file if it is proper file type\n * @param {Object} event - file select event that contains file\n */\n function handleDropFile(event: DragEvent) {\n if (props.disabled) {\n return;\n }\n\n const files = [...(event.dataTransfer?.files || [])];\n\n isDraggingOver.value = false;\n\n return processFiles(files);\n }\n\n function handleFileDelete(file: File) {\n emit('file-delete', file);\n }\n\n function readMimeType(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n if (file.type) {\n return resolve(file.type);\n } else if (window.FileReader) {\n const fileReader = new FileReader();\n\n fileReader.onload = () => {\n const mimeType =\n fileReader.result && (fileReader.result as string).match(/[^:]\\w+\\/[\\w-+\\d.]+(?=;|,)/)\n ? ((fileReader.result as string).match(/[^:]\\w+\\/[\\w-+\\d.]+(?=;|,)/) as string[])[0]\n : '';\n\n resolve(mimeType);\n };\n\n fileReader.readAsDataURL(file);\n } else {\n reject(new Error('Failed to read file.'));\n }\n });\n }\n</script>\n\n<template>\n <div class=\"stash-file-upload\" :class=\"attributes.class\" data-test=\"stash-file-upload\">\n <div v-if=\"buttonOnly\">\n <Button secondary type=\"button\" :disabled=\"disabled || null\" @click.stop.prevent=\"openFileDialog\">\n <slot name=\"submitText\">\n {{ t('ll.fileUpload.uploadFile') }}\n </slot>\n </Button>\n </div>\n <div\n v-else\n class=\"tw-rounded tw-p-6\"\n :class=\"[classes['file-dropbox'], isDraggingOver && classes['is-dragging'], disabled && classes['is-disabled']]\"\n @dragover.prevent=\"handleDragEnter\"\n @drop.prevent=\"handleDropFile\"\n @dragleave.prevent=\"handleDragLeave\"\n >\n <div\n class=\"tw-flex tw-flex-col tw-items-center tw-justify-center tw-text-center\"\n :class=\"[{ 'tw-items-center md:tw-flex-row': size === FileUploadSizes.Dense }]\"\n >\n <template v-if=\"!files.length\">\n <InlineSvg v-if=\"size !== FileUploadSizes.Dense\" :src=\"illustrationPath\" name=\"file\" width=\"84\" height=\"96\" />\n <span class=\"tw-text-ice-900\">\n {{ t('ll.fileUpload.dragDropFileHere') }}\n </span>\n <span\n :class=\"\n size === FileUploadSizes.Dense\n ? 'md:tw-ml-1.5 md:tw-mr-3 md:tw-my-0 tw-my-1.5 tw-text-ice-900'\n : 'tw-mt-1.5 tw-my-1.5'\n \"\n >\n {{ t('ll.fileUpload.or') }}\n </span>\n <Button\n class=\"tw-mt-1.5\"\n secondary\n type=\"button\"\n :class=\"classes['file-select-button']\"\n :disabled=\"disabled\"\n @click.stop.prevent=\"openFileDialog\"\n >\n <!-- @slot for custom submit text -->\n <slot name=\"submitText\">{{ t('ll.fileUpload.uploadFile') }}</slot>\n </Button>\n </template>\n <template v-else>\n <div v-for=\"file in files\" :key=\"file.name\">\n <Icon name=\"file\" />\n <span>{{ file.name }}</span>\n <Button :class=\"[classes['remove-button'], classes['button']]\" @click.stop.prevent=\"handleFileDelete(file)\">\n {{ t('ll.fileUpload.remove') }}\n </Button>\n </div>\n </template>\n </div>\n <div v-if=\"$slots.hint && !files.length\" class=\"tw-mt-6 tw-text-center tw-text-xs tw-text-ice-700\">\n <!-- @slot for displaying helpful text and/or links -->\n <slot name=\"hint\"></slot>\n </div>\n </div>\n <input\n v-show=\"false\"\n v-bind=\"inputAttrs\"\n ref=\"fileUploadRef\"\n data-test=\"stash-file-upload|input\"\n type=\"file\"\n :disabled=\"disabled\"\n :accept=\"acceptedMimeTypes.join(',')\"\n :multiple=\"props.multiple\"\n @change=\"handleFileInput\"\n />\n </div>\n</template>\n\n<style module>\n .file-dropbox {\n background: var(--color-ice-200);\n background-image: url(\"data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='4' ry='4' stroke='%23C5C9D4FF' stroke-width='1' stroke-dasharray='5 %2c 5' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e\");\n background-repeat: no-repeat;\n border: theme('borderWidth.DEFAULT') solid var(--color-ice-500);\n border-color: transparent;\n }\n\n .is-dragging {\n background-image: none;\n border-color: var(--color-ice-500);\n\n & > * {\n pointer-events: none;\n }\n }\n\n .is-disabled {\n cursor: no-drop;\n }\n\n /* Constrain the upload icon for drag/drop to the required size */\n .upload-icon {\n height: 98px;\n width: 84px;\n }\n\n .remove-button.button {\n background: transparent;\n border: none;\n color: var(--color-red-500);\n\n &:hover {\n background: transparent;\n border: none;\n }\n }\n</style>\n"],"names":["FILE_TYPES","FileUploadSizes","classes","useCssModule","isDraggingOver","ref","fileUploadRef","stashOptions","inject","attributes","useAttrs","inputAttrs","computed","attrs","concatArraysToFirst","a","b","acceptedMimeTypes","props","fileType","acceptedFileExtensions","illustrationPath","openFileDialog","handleDragEnter","handleDragLeave","handleFileError","error","message","t","emit","logger","areFileTypesAccepted","files","mimeTypes","file","readMimeType","mimeType","extension","processFiles","handleFileInput","event","_a","handleDropFile","handleFileDelete","resolve","reject","fileReader"],"mappings":"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"}
package/dist/Image.js CHANGED
@@ -10,7 +10,7 @@ function V({
10
10
  joinWith: f = "/",
11
11
  valueMap: i = {}
12
12
  } = {}) {
13
- const n = typeof e == "function" ? e : j(e);
13
+ const n = typeof e == "function" ? e : j(e || {});
14
14
  return Object.keys(i).forEach((c) => {
15
15
  typeof i[c] != "function" && (i[c] = j(i[c]));
16
16
  }), (c = {}) => Object.entries(c).map(([g, v]) => {
package/dist/Image.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Image.js","sources":["../src/components/Image/providers/utils.ts","../src/components/Image/providers/cloudinary.ts","../src/components/Image/providers/static.ts","../src/components/Image/providers/index.ts","../src/components/Image/Image.vue"],"sourcesContent":["export interface ImageModifiers {\n format?: string;\n height?: number;\n width?: number;\n [key: string]: any /* eslint-disable-line @typescript-eslint/no-explicit-any */;\n}\n\nexport type ParamFormatter = (key: string, value: string) => string;\n\nexport type ParamMapper = { [key: string]: string } | ((key: string) => string);\n\nexport interface ProviderUrlBuilder {\n keyMap?: ParamMapper;\n formatter?: ParamFormatter;\n joinWith?: string;\n valueMap?: {\n [key: string]: ParamMapper;\n };\n}\n\nfunction createMapper(map: any) {\n /* eslint-disable-line @typescript-eslint/no-explicit-any */\n return (key: string) => {\n return map[key] || key;\n };\n}\n\n/**\n * Builds the parameterized Cloudinary url\n */\nexport function buildProviderUrl({\n formatter = (key, value) => `${key}=${value}`,\n keyMap,\n joinWith = '/',\n valueMap = {},\n}: ProviderUrlBuilder = {}) {\n const keyMapper = typeof keyMap === 'function' ? keyMap : createMapper(keyMap);\n\n Object.keys(valueMap).forEach((valueKey) => {\n if (typeof valueMap[valueKey] !== 'function') {\n valueMap[valueKey] = createMapper(valueMap[valueKey]);\n }\n });\n\n return (modifiers: { [key: string]: string } = {}) => {\n const operations = Object.entries(modifiers).map(([key, value]) => {\n const mapper = valueMap[key];\n const newKey = keyMapper(key);\n let newVal = value;\n\n if (typeof mapper === 'function') {\n newVal = mapper(modifiers[key]);\n }\n\n return formatter(newKey, newVal);\n });\n\n return operations.join(joinWith);\n };\n}\n\n/**\n * Checks if a (sub)domain is included in a list of acceptable domains\n * @param str the (sub)domain to check\n * @param domains an array of valid domains\n */\nexport function isDomainValid(str = '', domains: string[] = []): boolean {\n const url = new URL(str);\n const host = url.host;\n\n return domains.some((domain) => {\n if (domain === host) {\n return true;\n }\n\n return domain.endsWith(`.${host}`);\n });\n}\n","import merge from 'lodash-es/merge';\n\nimport { IMAGE_PROVIDER_URLS } from '../../../constants';\nimport { buildProviderUrl, ImageModifiers } from './utils';\n\nconst BASE_URL = IMAGE_PROVIDER_URLS.CLOUDINARY;\n\nconst convertHextoRGBFormat = (value: string) => (value.startsWith('#') ? value.replace('#', 'rgb_') : value);\n\n/**\n * Parameters (option and value pairs) that can be used in the <transformations> segment of the Cloudinary transformation URL.\n * Options and their respective values are connected by an underscore (eg `w_250` for width of 250px.).\n * Multiple parameters are comma separated (eg. `w_250,h_250`).\n *\n * `keyMap` maps the option to its option prefix.\n * `valueMap` is used for grouping options using the same `keyMap` value under a 'category', allowing for easier usage and custom labelling in the component context.\n *\n * Transformation URL structure:\n * https://cloudinary.com/documentation/transformation_reference\n *\n * Transformation URL parameters (options and values):\n * https://cloudinary.com/documentation/image_transformations#transformation_url_syntax\n *\n */\nexport const operationsGenerator = buildProviderUrl({\n keyMap: {\n fit: 'c',\n width: 'w',\n height: 'h',\n format: 'f',\n quality: 'q',\n background: 'b',\n dpr: 'dpr',\n },\n valueMap: {\n fit: {\n fill: 'fill',\n inside: 'pad',\n outside: 'lpad',\n cover: 'fit',\n contain: 'scale',\n },\n format: {\n jpeg: 'jpg',\n },\n background(value: string) {\n return convertHextoRGBFormat(value);\n },\n },\n joinWith: ',',\n formatter: (key, value) => `${key}_${value}`,\n});\n\n// Note: Not configurable via Image props (for now).\nconst defaultModifiers = {\n // defaulting to maintain original image format to reduce transformations\n // format: 'auto',\n quality: 'auto',\n};\n\nexport function getImageUrl(src: string, modifiers: Partial<ImageModifiers> = {}): string {\n const mergeModifiers = merge(defaultModifiers, modifiers);\n const operations = operationsGenerator(mergeModifiers);\n\n return `${BASE_URL}/${operations}/${src}`;\n}\n","export function getImageUrl(src = ''): string {\n return src;\n}\n","import * as cloudinary from './cloudinary';\nimport * as staticProvider from './static';\n\nexport default {\n cloudinary,\n static: staticProvider,\n};\n","<script lang=\"ts\">\n export const PRESET_SIZES = {\n xsmall: {\n alwaysIncluded: false,\n width: 160,\n },\n small: {\n alwaysIncluded: true,\n width: 338,\n },\n medium: {\n alwaysIncluded: true,\n width: 676,\n },\n large: {\n alwaysIncluded: true,\n width: 1352,\n },\n xlarge: {\n alwaysIncluded: false,\n width: 2704,\n },\n } as const;\n\n export enum ImageRadiuses {\n None = 'none',\n Rounded = 'rounded',\n }\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, useAttrs } from 'vue';\n\n import { StashImageProviders, StashProvideState } from '../../../types/misc';\n import { SCREEN_SIZES } from '../../constants';\n import providers from './providers';\n import { ImageModifiers, isDomainValid } from './providers/utils';\n\n // interface ImagePresetSizes {\n // [size: string]: {\n // alwaysIncluded: boolean;\n // width: number;\n // }\n // }\n\n export interface ImageSizeVariant {\n media: string;\n preset?: keyof typeof PRESET_SIZES;\n screenMinWidth: number;\n size: string;\n }\n\n export type ImageRadius = `${ImageRadiuses}`;\n\n export interface ImageProps {\n /**\n * The path to the image you want to embed.\n */\n src: string;\n\n /**\n * Native srcset attribute.\n * One or more strings separated by commas, indicating possible image sources\n * Can only be used with provider=static, otherwise it's ignored and auto-generated with `sizes` usage\n */\n srcset?: string;\n\n /**\n * For specifying responsive sizes\n */\n sizes?: string;\n\n /**\n * Where the image is served from.\n * Optional, and when provided it forces the provider used.\n *\n * The provider is otherwise inherited from the Stash config `stashOptions.images.provider`, which defaults to `cloudinary`.\n *\n * When not provided, the provider is also inferred by `isStatic`:\n * - `static` for relative/absolute paths (`img/foo.jpg` or `/static/img/bar.jpg`), or when whitelisted absolute URLs are used (included in `staticOptions.images.staticDomains`).\n */\n provider?: StashImageProviders;\n\n /**\n * For applying border radius\n */\n radius?: ImageRadius;\n\n /**\n * TODO - https://leaflink.atlassian.net/browse/GRO-204\n * A custom function used to resolve a URL string for the image\n */\n // loader?: () => string;\n }\n\n const PROVIDERS = {\n CLOUDINARY: 'cloudinary',\n STATIC: 'static',\n };\n const BREAKPOINTS = {\n md: SCREEN_SIZES.md,\n lg: SCREEN_SIZES.lg,\n };\n const stashOptions = inject<StashProvideState>('stashOptions');\n const props = withDefaults(defineProps<ImageProps>(), {\n src: '',\n srcset: '',\n sizes: '',\n provider: undefined,\n radius: 'none',\n // loader: undefined, // TODO - https://leaflink.atlassian.net/browse/GRO-204\n });\n\n const attrs = computed(() => {\n const { src, ...attrs } = useAttrs();\n\n attrs.sizes = imgSizes.value;\n attrs.srcset = imgSrcset.value;\n\n return attrs;\n });\n\n const staticDomains = computed(() => stashOptions?.images?.staticDomains || []);\n\n const isStaticUrl = computed(() => {\n // return true if not an absolute url\n try {\n new URL(props.src);\n } catch (e) {\n return true;\n }\n\n // true if domain is whitelisted for static usage\n return isDomainValid(props.src, staticDomains.value);\n });\n\n const computedProvider = computed(() => {\n if (props.provider) {\n return props.provider;\n }\n\n if (stashOptions?.images?.provider && stashOptions.images.provider !== PROVIDERS.STATIC && !isStaticUrl.value) {\n return stashOptions.images.provider;\n }\n\n return PROVIDERS.STATIC;\n });\n\n const isStatic = computed(() => computedProvider.value === PROVIDERS.STATIC);\n\n const imgProvider = computed(() => providers[computedProvider.value]);\n\n const imgSrc = computed(() =>\n isStatic.value ? getProviderImage() : getProviderImage({ width: PRESET_SIZES.medium.width }),\n );\n\n const imgSizes = computed(() => (props.sizes || !isStatic.value ? getSizes() : undefined));\n\n const imgSrcset = computed(() => (props.sizes && !props.srcset && !isStatic.value ? getSources() : props.srcset));\n\n const parsedSizes = computed(() => {\n if (props.sizes) {\n return parseSizes(props.sizes);\n }\n\n if (!isStatic.value) {\n return parseSizes('lg:large');\n }\n\n return [];\n });\n\n function getProviderImage(modifiers: ImageModifiers = {}) {\n return imgProvider.value.getImageUrl(props.src, modifiers);\n }\n\n function getSources() {\n const appliedPresets = Object.entries(PRESET_SIZES).reduce((obj, [key, entry]) => {\n const isPreset = !!parsedSizes.value.find((size) => size.preset === key);\n\n if (isPreset || entry.alwaysIncluded) {\n obj[key] = entry;\n }\n\n return obj;\n }, {} as typeof PRESET_SIZES);\n\n return Object.values(appliedPresets)\n .map((size) => {\n const width = size.width;\n const src = getProviderImage({ width });\n\n return `${src} ${size.width}w`;\n })\n .join(', ');\n }\n\n function getSizes() {\n return parsedSizes.value.map((v) => `${v.media ? v.media + ' ' : ''}${v.size}`).join(', ');\n }\n\n function parseSizes(providedSizes: string) {\n const variants: ImageSizeVariant[] = [];\n const sizes = {\n default: '100vw',\n };\n\n // parse sizes and convert to object\n if (typeof providedSizes === 'string') {\n const definitions = providedSizes.split(/[\\s]+/).filter((size) => size);\n\n for (const entry of definitions) {\n const size = entry.split(':');\n\n if (size.length !== 2) {\n sizes['default'] = size[0].trim();\n continue;\n }\n\n sizes[size[0].trim()] = size[1].trim();\n }\n } else {\n throw new Error('`sizes` needs to be a string');\n }\n\n for (const key in sizes) {\n const screenMinWidth = parseInt(BREAKPOINTS[key] || 0);\n const sizeValue = sizes[key];\n const presetKey = PRESET_SIZES[sizeValue] ? sizeValue : undefined;\n let size = String(presetKey ? PRESET_SIZES[sizeValue].width : sizeValue);\n const isFluid = size.endsWith('vw');\n\n // default integers to pixels\n if (!isFluid && /^\\d+$/.test(size)) {\n size = `${size}px`;\n }\n\n // ignore invalid size\n if (!isFluid && !size.endsWith('px')) {\n continue;\n }\n\n const variant = {\n media: screenMinWidth ? `(min-width: ${screenMinWidth}px)` : '',\n preset: presetKey,\n screenMinWidth,\n size,\n };\n\n variants.push(variant);\n }\n\n variants.sort((v1, v2) => (v1.screenMinWidth > v2.screenMinWidth ? -1 : 1));\n\n return variants;\n }\n</script>\n\n<template>\n <img\n ref=\"img\"\n :key=\"imgSrc\"\n data-test=\"stash-image\"\n class=\"stash-image\"\n :class=\"{\n 'tw-rounded': props.radius === ImageRadiuses.Rounded,\n }\"\n :src=\"imgSrc\"\n v-bind=\"attrs\"\n />\n</template>\n"],"names":["createMapper","map","key","buildProviderUrl","formatter","value","keyMap","joinWith","valueMap","keyMapper","valueKey","modifiers","mapper","newKey","newVal","isDomainValid","str","domains","host","domain","BASE_URL","IMAGE_PROVIDER_URLS","convertHextoRGBFormat","operationsGenerator","defaultModifiers","getImageUrl","src","mergeModifiers","merge","operations","providers","cloudinary","staticProvider","PRESET_SIZES","ImageRadiuses","PROVIDERS","BREAKPOINTS","SCREEN_SIZES","stashOptions","inject","attrs","computed","useAttrs","imgSizes","imgSrcset","staticDomains","_a","isStaticUrl","props","computedProvider","isStatic","imgProvider","imgSrc","getProviderImage","getSizes","getSources","parsedSizes","parseSizes","appliedPresets","obj","entry","size","width","v","providedSizes","variants","sizes","definitions","screenMinWidth","sizeValue","presetKey","isFluid","variant","v1","v2"],"mappings":"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"}
1
+ {"version":3,"file":"Image.js","sources":["../src/components/Image/providers/utils.ts","../src/components/Image/providers/cloudinary.ts","../src/components/Image/providers/static.ts","../src/components/Image/providers/index.ts","../src/components/Image/Image.vue"],"sourcesContent":["export interface ImageModifiers {\n format?: string;\n height?: number;\n width?: number;\n [key: string]: any /* eslint-disable-line @typescript-eslint/no-explicit-any */;\n}\n\nexport type ParamFormatter = (key: string, value: string) => string;\n\nexport type ParamMapper = { [key: string]: string } | ((key: string) => string);\n\nexport interface ProviderUrlBuilder {\n keyMap?: ParamMapper;\n formatter?: ParamFormatter;\n joinWith?: string;\n valueMap?: {\n [key: string]: ParamMapper;\n };\n}\n\nfunction createMapper(map: ParamMapper) {\n return (key: string) => {\n return map[key] || key;\n };\n}\n\n/**\n * Builds the parameterized Cloudinary url\n */\nexport function buildProviderUrl({\n formatter = (key, value) => `${key}=${value}`,\n keyMap,\n joinWith = '/',\n valueMap = {},\n}: ProviderUrlBuilder = {}) {\n const keyMapper = typeof keyMap === 'function' ? keyMap : createMapper(keyMap || {});\n\n Object.keys(valueMap).forEach((valueKey) => {\n if (typeof valueMap[valueKey] !== 'function') {\n valueMap[valueKey] = createMapper(valueMap[valueKey]);\n }\n });\n\n return (modifiers: { [key: string]: string } = {}) => {\n const operations = Object.entries(modifiers).map(([key, value]) => {\n const mapper = valueMap[key];\n const newKey = keyMapper(key);\n let newVal = value;\n\n if (typeof mapper === 'function') {\n newVal = mapper(modifiers[key]);\n }\n\n return formatter(newKey, newVal);\n });\n\n return operations.join(joinWith);\n };\n}\n\n/**\n * Checks if a (sub)domain is included in a list of acceptable domains\n * @param str the (sub)domain to check\n * @param domains an array of valid domains\n */\nexport function isDomainValid(str = '', domains: string[] = []): boolean {\n const url = new URL(str);\n const host = url.host;\n\n return domains.some((domain) => {\n if (domain === host) {\n return true;\n }\n\n return domain.endsWith(`.${host}`);\n });\n}\n","import merge from 'lodash-es/merge';\n\nimport { IMAGE_PROVIDER_URLS } from '../../../constants';\nimport { buildProviderUrl, ImageModifiers } from './utils';\n\nconst BASE_URL = IMAGE_PROVIDER_URLS.CLOUDINARY;\n\nconst convertHextoRGBFormat = (value: string) => (value.startsWith('#') ? value.replace('#', 'rgb_') : value);\n\n/**\n * Parameters (option and value pairs) that can be used in the <transformations> segment of the Cloudinary transformation URL.\n * Options and their respective values are connected by an underscore (eg `w_250` for width of 250px.).\n * Multiple parameters are comma separated (eg. `w_250,h_250`).\n *\n * `keyMap` maps the option to its option prefix.\n * `valueMap` is used for grouping options using the same `keyMap` value under a 'category', allowing for easier usage and custom labelling in the component context.\n *\n * Transformation URL structure:\n * https://cloudinary.com/documentation/transformation_reference\n *\n * Transformation URL parameters (options and values):\n * https://cloudinary.com/documentation/image_transformations#transformation_url_syntax\n *\n */\nexport const operationsGenerator = buildProviderUrl({\n keyMap: {\n fit: 'c',\n width: 'w',\n height: 'h',\n format: 'f',\n quality: 'q',\n background: 'b',\n dpr: 'dpr',\n },\n valueMap: {\n fit: {\n fill: 'fill',\n inside: 'pad',\n outside: 'lpad',\n cover: 'fit',\n contain: 'scale',\n },\n format: {\n jpeg: 'jpg',\n },\n background(value: string) {\n return convertHextoRGBFormat(value);\n },\n },\n joinWith: ',',\n formatter: (key, value) => `${key}_${value}`,\n});\n\n// Note: Not configurable via Image props (for now).\nconst defaultModifiers = {\n // defaulting to maintain original image format to reduce transformations\n // format: 'auto',\n quality: 'auto',\n};\n\nexport function getImageUrl(src: string, modifiers: Partial<ImageModifiers> = {}): string {\n const mergeModifiers = merge(defaultModifiers, modifiers);\n const operations = operationsGenerator(mergeModifiers);\n\n return `${BASE_URL}/${operations}/${src}`;\n}\n","export function getImageUrl(src = ''): string {\n return src;\n}\n","import * as cloudinary from './cloudinary';\nimport * as staticProvider from './static';\n\nexport default {\n cloudinary,\n static: staticProvider,\n};\n","<script lang=\"ts\">\n export const PRESET_SIZES = {\n xsmall: {\n alwaysIncluded: false,\n width: 160,\n },\n small: {\n alwaysIncluded: true,\n width: 338,\n },\n medium: {\n alwaysIncluded: true,\n width: 676,\n },\n large: {\n alwaysIncluded: true,\n width: 1352,\n },\n xlarge: {\n alwaysIncluded: false,\n width: 2704,\n },\n } as const;\n\n export enum ImageRadiuses {\n None = 'none',\n Rounded = 'rounded',\n }\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, useAttrs } from 'vue';\n\n import { StashImageProviders, StashProvideState } from '../../../types/misc';\n import { SCREEN_SIZES } from '../../constants';\n import providers from './providers';\n import { ImageModifiers, isDomainValid } from './providers/utils';\n\n // interface ImagePresetSizes {\n // [size: string]: {\n // alwaysIncluded: boolean;\n // width: number;\n // }\n // }\n\n export interface ImageSizeVariant {\n media: string;\n preset?: keyof typeof PRESET_SIZES;\n screenMinWidth: number;\n size: string;\n }\n\n export type ImageRadius = `${ImageRadiuses}`;\n\n export interface ImageProps {\n /**\n * The path to the image you want to embed.\n */\n src: string;\n\n /**\n * Native srcset attribute.\n * One or more strings separated by commas, indicating possible image sources\n * Can only be used with provider=static, otherwise it's ignored and auto-generated with `sizes` usage\n */\n srcset?: string;\n\n /**\n * For specifying responsive sizes\n */\n sizes?: string;\n\n /**\n * Where the image is served from.\n * Optional, and when provided it forces the provider used.\n *\n * The provider is otherwise inherited from the Stash config `stashOptions.images.provider`, which defaults to `cloudinary`.\n *\n * When not provided, the provider is also inferred by `isStatic`:\n * - `static` for relative/absolute paths (`img/foo.jpg` or `/static/img/bar.jpg`), or when whitelisted absolute URLs are used (included in `staticOptions.images.staticDomains`).\n */\n provider?: StashImageProviders;\n\n /**\n * For applying border radius\n */\n radius?: ImageRadius;\n\n /**\n * TODO - https://leaflink.atlassian.net/browse/GRO-204\n * A custom function used to resolve a URL string for the image\n */\n // loader?: () => string;\n }\n\n const PROVIDERS = {\n CLOUDINARY: 'cloudinary',\n STATIC: 'static',\n };\n const BREAKPOINTS = {\n md: SCREEN_SIZES.md,\n lg: SCREEN_SIZES.lg,\n };\n const stashOptions = inject<StashProvideState>('stashOptions');\n const props = withDefaults(defineProps<ImageProps>(), {\n src: '',\n srcset: '',\n sizes: '',\n provider: undefined,\n radius: 'none',\n // loader: undefined, // TODO - https://leaflink.atlassian.net/browse/GRO-204\n });\n\n const attrs = computed(() => {\n const { src, ...attrs } = useAttrs();\n\n attrs.sizes = imgSizes.value;\n attrs.srcset = imgSrcset.value;\n\n return attrs;\n });\n\n const staticDomains = computed(() => stashOptions?.images?.staticDomains || []);\n\n const isStaticUrl = computed(() => {\n // return true if not an absolute url\n try {\n new URL(props.src);\n } catch (e) {\n return true;\n }\n\n // true if domain is whitelisted for static usage\n return isDomainValid(props.src, staticDomains.value);\n });\n\n const computedProvider = computed(() => {\n if (props.provider) {\n return props.provider;\n }\n\n if (stashOptions?.images?.provider && stashOptions.images.provider !== PROVIDERS.STATIC && !isStaticUrl.value) {\n return stashOptions.images.provider;\n }\n\n return PROVIDERS.STATIC;\n });\n\n const isStatic = computed(() => computedProvider.value === PROVIDERS.STATIC);\n\n const imgProvider = computed(() => providers[computedProvider.value]);\n\n const imgSrc = computed(() =>\n isStatic.value ? getProviderImage() : getProviderImage({ width: PRESET_SIZES.medium.width }),\n );\n\n const imgSizes = computed(() => (props.sizes || !isStatic.value ? getSizes() : undefined));\n\n const imgSrcset = computed(() => (props.sizes && !props.srcset && !isStatic.value ? getSources() : props.srcset));\n\n const parsedSizes = computed(() => {\n if (props.sizes) {\n return parseSizes(props.sizes);\n }\n\n if (!isStatic.value) {\n return parseSizes('lg:large');\n }\n\n return [];\n });\n\n function getProviderImage(modifiers: ImageModifiers = {}) {\n return imgProvider.value.getImageUrl(props.src, modifiers);\n }\n\n function getSources() {\n const appliedPresets = Object.entries(PRESET_SIZES).reduce((obj, [key, entry]) => {\n const isPreset = !!parsedSizes.value.find((size) => size.preset === key);\n\n if (isPreset || entry.alwaysIncluded) {\n obj[key] = entry;\n }\n\n return obj;\n }, {} as typeof PRESET_SIZES);\n\n return Object.values(appliedPresets)\n .map((size) => {\n const width = size.width;\n const src = getProviderImage({ width });\n\n return `${src} ${size.width}w`;\n })\n .join(', ');\n }\n\n function getSizes() {\n return parsedSizes.value.map((v) => `${v.media ? v.media + ' ' : ''}${v.size}`).join(', ');\n }\n\n function parseSizes(providedSizes: string) {\n const variants: ImageSizeVariant[] = [];\n const sizes = {\n default: '100vw',\n };\n\n // parse sizes and convert to object\n if (typeof providedSizes === 'string') {\n const definitions = providedSizes.split(/[\\s]+/).filter((size) => size);\n\n for (const entry of definitions) {\n const size = entry.split(':');\n\n if (size.length !== 2) {\n sizes['default'] = size[0].trim();\n continue;\n }\n\n sizes[size[0].trim()] = size[1].trim();\n }\n } else {\n throw new Error('`sizes` needs to be a string');\n }\n\n for (const key in sizes) {\n const screenMinWidth = parseInt(BREAKPOINTS[key] || 0);\n const sizeValue = sizes[key];\n const presetKey = PRESET_SIZES[sizeValue] ? sizeValue : undefined;\n let size = String(presetKey ? PRESET_SIZES[sizeValue].width : sizeValue);\n const isFluid = size.endsWith('vw');\n\n // default integers to pixels\n if (!isFluid && /^\\d+$/.test(size)) {\n size = `${size}px`;\n }\n\n // ignore invalid size\n if (!isFluid && !size.endsWith('px')) {\n continue;\n }\n\n const variant = {\n media: screenMinWidth ? `(min-width: ${screenMinWidth}px)` : '',\n preset: presetKey,\n screenMinWidth,\n size,\n };\n\n variants.push(variant);\n }\n\n variants.sort((v1, v2) => (v1.screenMinWidth > v2.screenMinWidth ? -1 : 1));\n\n return variants;\n }\n</script>\n\n<template>\n <img\n ref=\"img\"\n :key=\"imgSrc\"\n data-test=\"stash-image\"\n class=\"stash-image\"\n :class=\"{\n 'tw-rounded': props.radius === ImageRadiuses.Rounded,\n }\"\n :src=\"imgSrc\"\n v-bind=\"attrs\"\n />\n</template>\n"],"names":["createMapper","map","key","buildProviderUrl","formatter","value","keyMap","joinWith","valueMap","keyMapper","valueKey","modifiers","mapper","newKey","newVal","isDomainValid","str","domains","host","domain","BASE_URL","IMAGE_PROVIDER_URLS","convertHextoRGBFormat","operationsGenerator","defaultModifiers","getImageUrl","src","mergeModifiers","merge","operations","providers","cloudinary","staticProvider","PRESET_SIZES","ImageRadiuses","PROVIDERS","BREAKPOINTS","SCREEN_SIZES","stashOptions","inject","attrs","computed","useAttrs","imgSizes","imgSrcset","staticDomains","_a","isStaticUrl","props","computedProvider","isStatic","imgProvider","imgSrc","getProviderImage","getSizes","getSources","parsedSizes","parseSizes","appliedPresets","obj","entry","size","width","v","providedSizes","variants","sizes","definitions","screenMinWidth","sizeValue","presetKey","isFluid","variant","v1","v2"],"mappings":"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"}
@@ -5,32 +5,50 @@ declare interface Config {
5
5
  message?: ValidationMessage;
6
6
  }
7
7
 
8
+ declare interface Config_10 {
9
+ message?: ValidationMessage;
10
+ }
11
+
8
12
  declare interface Config_2 {
9
13
  max: MaybeRefOrGetter<number>;
10
14
  message?: ValidationMessage;
15
+ trim?: boolean;
11
16
  }
12
17
 
13
18
  declare interface Config_3 {
14
- min: MaybeRefOrGetter<number>;
19
+ max: MaybeRefOrGetter<number>;
15
20
  message?: ValidationMessage;
16
21
  }
17
22
 
18
23
  declare interface Config_4 {
24
+ min: MaybeRefOrGetter<number>;
19
25
  message?: ValidationMessage;
26
+ trim?: boolean;
20
27
  }
21
28
 
22
29
  declare interface Config_5 {
30
+ min: MaybeRefOrGetter<number>;
23
31
  message?: ValidationMessage;
24
32
  }
25
33
 
26
34
  declare interface Config_6 {
27
- message?: ValidationMessage;
35
+ regex: RegExp;
36
+ /** A custom message is required in order to inform the user of the required pattern. */
37
+ message: ValidationMessage;
28
38
  }
29
39
 
30
40
  declare interface Config_7 {
31
41
  message?: ValidationMessage;
32
42
  }
33
43
 
44
+ declare interface Config_8 {
45
+ message?: ValidationMessage;
46
+ }
47
+
48
+ declare interface Config_9 {
49
+ message?: ValidationMessage;
50
+ }
51
+
34
52
  export declare function email(config?: Config): ValidationRule;
35
53
 
36
54
  /**
@@ -39,15 +57,21 @@ export declare function email(config?: Config): ValidationRule;
39
57
  */
40
58
  export declare function isDefined(value: unknown): boolean;
41
59
 
42
- export declare function maxValue(config: Config_2): ValidationRule;
60
+ export declare function maxLength(config: Config_2): ValidationRule;
61
+
62
+ export declare function maxValue(config: Config_3): ValidationRule;
63
+
64
+ export declare function minLength(config: Config_4): ValidationRule;
65
+
66
+ export declare function minValue(config: Config_5): ValidationRule;
43
67
 
44
- export declare function minValue(config: Config_3): ValidationRule;
68
+ export declare function pattern(config: Config_6): ValidationRule;
45
69
 
46
- export declare function positiveNumber(config?: Config_4): ValidationRule;
70
+ export declare function positiveNumber(config?: Config_7): ValidationRule;
47
71
 
48
- export declare function price(config?: Config_5): ValidationRule;
72
+ export declare function price(config?: Config_8): ValidationRule;
49
73
 
50
- export declare function required(config?: Config_6): ValidationRule;
74
+ export declare function required(config?: Config_9): ValidationRule;
51
75
 
52
76
  declare function useValidation<Values extends object>({ rules, values, }: UseValidationArgs<Values>): ValidationGroup<Values>;
53
77
  export default useValidation;
@@ -195,6 +219,6 @@ export declare type ValidationRules<Values extends object> = {
195
219
  */
196
220
  export declare type Validator<Value = unknown> = (value: Value) => boolean;
197
221
 
198
- export declare function wholeNumber(config?: Config_7): ValidationRule;
222
+ export declare function wholeNumber(config?: Config_10): ValidationRule;
199
223
 
200
224
  export { }
@@ -1,201 +1,246 @@
1
1
  import O from "lodash-es/debounce";
2
- import E from "lodash-es/get";
3
- import { toValue as f, computed as c, ref as T, watch as A, reactive as S, nextTick as w, readonly as N } from "vue";
4
- import { DECIMAL_PRECISION as D, DEBOUNCE as j } from "./constants.js";
5
- import { t as d } from "./locale.js";
6
- import { i as v } from "./isDefined-2ce6cde4.js";
7
- import C from "lodash-es/round";
8
- function q(t) {
9
- return t && t.constructor && typeof t.constructor.isBuffer == "function" && t.constructor.isBuffer(t);
2
+ import S from "lodash-es/get";
3
+ import { toValue as u, computed as c, ref as w, watch as L, reactive as T, nextTick as I, readonly as V } from "vue";
4
+ import { DECIMAL_PRECISION as A, DEBOUNCE as q } from "./constants.js";
5
+ import { t as f } from "./locale.js";
6
+ import { i as l } from "./isDefined-2ce6cde4.js";
7
+ import D from "lodash-es/round";
8
+ function j(e) {
9
+ return e && e.constructor && typeof e.constructor.isBuffer == "function" && e.constructor.isBuffer(e);
10
10
  }
11
- function B(t) {
12
- return t;
11
+ function C(e) {
12
+ return e;
13
13
  }
14
- function F(t, e) {
15
- e = e || {};
16
- const a = e.delimiter || ".", i = e.maxDepth, o = e.transformKey || B, u = {};
17
- function g(h, y, m) {
18
- m = m || 1, Object.keys(h).forEach(function(b) {
19
- const r = h[b], V = e.safe && Array.isArray(r), n = Object.prototype.toString.call(r), s = q(r), p = n === "[object Object]" || n === "[object Array]", l = y ? y + a + o(b) : o(b);
20
- if (!V && !s && p && Object.keys(r).length && (!e.maxDepth || m < i))
21
- return g(r, l, m + 1);
22
- u[l] = r;
14
+ function F(e, t) {
15
+ t = t || {};
16
+ const i = t.delimiter || ".", o = t.maxDepth, s = t.transformKey || C, m = {};
17
+ function v(h, y, g) {
18
+ g = g || 1, Object.keys(h).forEach(function(p) {
19
+ const r = h[p], x = t.safe && Array.isArray(r), n = Object.prototype.toString.call(r), a = j(r), b = n === "[object Object]" || n === "[object Array]", d = y ? y + i + s(p) : s(p);
20
+ if (!x && !a && b && Object.keys(r).length && (!t.maxDepth || g < o))
21
+ return v(r, d, g + 1);
22
+ m[d] = r;
23
23
  });
24
24
  }
25
- return g(t), u;
25
+ return v(e), m;
26
26
  }
27
- function P(t = {}) {
27
+ function P(e = {}) {
28
28
  return {
29
29
  name: "email",
30
- validator(e) {
31
- return !v(e) || typeof e == "string" && /^\S+@\S+\.\S+$/.test(e);
30
+ validator(t) {
31
+ return !l(t) || typeof t == "string" && /^\S+@\S+\.\S+$/.test(t);
32
32
  },
33
- message: t.message || d("ll.validation.email")
33
+ message: e.message || f("ll.validation.email")
34
34
  };
35
35
  }
36
- function Y(t) {
36
+ function Y(e) {
37
+ return {
38
+ name: "maxLength",
39
+ validator(t) {
40
+ const i = u(e.max), o = u(t);
41
+ if (!l(o))
42
+ return !0;
43
+ let s = String(o);
44
+ return e.trim && (s = s.trim()), s.length <= i;
45
+ },
46
+ message: e.message || (() => f("ll.validation.maxLength", { max: String(u(e.max)) }))
47
+ };
48
+ }
49
+ function z(e) {
37
50
  return {
38
51
  name: "maxValue",
39
- validator(e) {
40
- const a = f(t.max);
41
- return !v(e) || Number(e) <= a;
52
+ validator(t) {
53
+ const i = u(e.max);
54
+ return !l(t) || Number(t) <= i;
55
+ },
56
+ message: e.message || (() => f("ll.validation.maxValue", { max: String(u(e.max)) }))
57
+ };
58
+ }
59
+ function G(e) {
60
+ return {
61
+ name: "minLength",
62
+ validator(t) {
63
+ const i = u(e.min), o = u(t);
64
+ if (!l(o))
65
+ return !0;
66
+ let s = String(o);
67
+ return e.trim && (s = s.trim()), s.length >= i;
42
68
  },
43
- message: t.message || (() => d("ll.validation.maxValue", { max: String(f(t.max)) }))
69
+ message: e.message || (() => f("ll.validation.minLength", { min: String(u(e.min)) }))
44
70
  };
45
71
  }
46
- function z(t) {
72
+ function H(e) {
47
73
  return {
48
74
  name: "minValue",
49
- validator(e) {
50
- const a = f(t.min);
51
- return !v(e) || Number(e) >= a;
75
+ validator(t) {
76
+ const i = u(e.min);
77
+ return !l(t) || Number(t) >= i;
78
+ },
79
+ message: e.message || (() => f("ll.validation.minValue", { min: String(u(e.min)) }))
80
+ };
81
+ }
82
+ function J(e) {
83
+ return {
84
+ name: "pattern",
85
+ validator(t) {
86
+ const i = u(t);
87
+ return !l(i) || e.regex.test(String(i));
52
88
  },
53
- message: t.message || (() => d("ll.validation.minValue", { min: String(f(t.min)) }))
89
+ message: () => {
90
+ if (typeof e.message != "string" || !e.message.trim())
91
+ throw new Error(
92
+ 'The "pattern" ruleFactory requires a custom message informing the user of the required pattern.'
93
+ );
94
+ return e.message;
95
+ }
54
96
  };
55
97
  }
56
- function G(t = {}) {
98
+ function Q(e = {}) {
57
99
  return {
58
100
  name: "positiveNumber",
59
- validator(e) {
60
- return !v(e) || Number(e) > 0;
101
+ validator(t) {
102
+ return !l(t) || Number(t) > 0;
61
103
  },
62
- message: t.message || d("ll.validation.positiveNumber")
104
+ message: e.message || f("ll.validation.positiveNumber")
63
105
  };
64
106
  }
65
- function H(t = {}) {
107
+ function X(e = {}) {
66
108
  return {
67
109
  name: "price",
68
- validator(e) {
69
- const a = Number(e);
70
- return !v(e) || a !== 1 / 0 && a >= 0 && a === C(a, D.CURRENCY);
110
+ validator(t) {
111
+ const i = Number(t);
112
+ return !l(t) || i !== 1 / 0 && i >= 0 && i === D(i, A.CURRENCY);
71
113
  },
72
- message: t.message || d("ll.validation.price")
114
+ message: e.message || f("ll.validation.price")
73
115
  };
74
116
  }
75
- function J(t = {}) {
117
+ function Z(e = {}) {
76
118
  return {
77
119
  name: "required",
78
- validator(e) {
79
- return v(typeof e == "string" ? e.trim() : e);
120
+ validator(t) {
121
+ return l(typeof t == "string" ? t.trim() : t);
80
122
  },
81
- message: t.message || d("ll.validation.required")
123
+ message: e.message || f("ll.validation.required")
82
124
  };
83
125
  }
84
- function Q(t = {}) {
126
+ function W(e = {}) {
85
127
  return {
86
128
  name: "wholeNumber",
87
- validator(e) {
88
- return !v(e) || Number.isInteger(Number(e)) && Number(e) >= 0;
129
+ validator(t) {
130
+ return !l(t) || Number.isInteger(Number(t)) && Number(t) >= 0;
89
131
  },
90
- message: t.message || d("ll.validation.wholeNumber")
132
+ message: e.message || f("ll.validation.wholeNumber")
91
133
  };
92
134
  }
93
- function X({
94
- rules: t,
95
- values: e
135
+ function ee({
136
+ rules: e,
137
+ values: t
96
138
  }) {
97
- const i = c(() => Object.keys(F(t, { safe: !0 }))).value.reduce((n, s) => {
98
- const p = T(E(f(e), s)), l = (I) => {
99
- p.value = E(f(e), I);
100
- }, x = O(() => {
101
- l(s);
102
- }, j.FAST);
103
- return A(
104
- () => E(f(e), s),
139
+ const o = c(() => Object.keys(F(e, { safe: !0 }))).value.reduce((n, a) => {
140
+ const b = w(S(u(t), a)), d = (N) => {
141
+ b.value = S(u(t), N);
142
+ }, E = O(() => {
143
+ d(a);
144
+ }, q.FAST);
145
+ return L(
146
+ () => S(u(t), a),
105
147
  () => {
106
- x();
148
+ E();
107
149
  }
108
- ), n[s] = M({
109
- fieldName: s,
110
- fieldValue: p,
150
+ ), n[a] = B({
151
+ fieldName: a,
152
+ fieldValue: b,
111
153
  flush: () => {
112
- x.cancel(), l(s);
154
+ E.cancel(), d(a);
113
155
  },
114
- rules: E(t, s)
156
+ rules: S(e, a)
115
157
  }), n;
116
- }, {}), o = c(() => Object.values(i)), u = c(() => o.value.some((n) => n.errors.length > 0)), g = c(() => o.value.some((n) => n.isTouched)), h = c(() => o.value.filter((n) => n.isDirty));
117
- return S({
158
+ }, {}), s = c(() => Object.values(o)), m = c(() => s.value.some((n) => n.errors.length > 0)), v = c(() => s.value.some((n) => n.isTouched)), h = c(() => s.value.filter((n) => n.isDirty));
159
+ return T({
118
160
  validate: async function({ preventScroll: n } = {}) {
119
- if (o.value.forEach((s) => {
120
- s.setTouched(!1), s.setTouched(!0);
121
- }), await w(), u.value && !n) {
122
- const s = Object.entries(i).find(([x, I]) => I.errorMessage), p = (s == null ? void 0 : s[0]) || "", l = document == null ? void 0 : document.querySelector(`[name=${p}]`);
123
- l && l.scrollIntoView({ behavior: "smooth" });
161
+ if (s.value.forEach((a) => {
162
+ a.setTouched(!1), a.setTouched(!0);
163
+ }), await I(), m.value && !n) {
164
+ const a = Object.entries(o).find(([E, N]) => N.errorMessage), b = (a == null ? void 0 : a[0]) || "", d = document == null ? void 0 : document.querySelector(`[name=${b}]`);
165
+ d && d.scrollIntoView({ behavior: "smooth" });
124
166
  }
125
- return !u.value;
167
+ return !m.value;
126
168
  },
127
169
  getError: function(n) {
128
- var s;
129
- return ((s = i[n]) == null ? void 0 : s.errorMessage) || "";
170
+ var a;
171
+ return ((a = o[n]) == null ? void 0 : a.errorMessage) || "";
130
172
  },
131
173
  touch: function(n) {
132
- if (!i[n])
174
+ if (!o[n])
133
175
  throw new Error(`In touch: fieldName "${n}" does not exist in the validation fields.`);
134
- i[n].setTouched();
176
+ o[n].setTouched();
135
177
  },
136
178
  setAllUntouched: async function() {
137
- await w(), o.value.forEach((n) => {
179
+ await I(), s.value.forEach((n) => {
138
180
  n.setTouched(!1);
139
181
  });
140
182
  },
141
183
  setInitialValues: function(n) {
142
- o.value.forEach((s) => {
143
- s.setInitialValue(n[s.name]);
184
+ s.value.forEach((a) => {
185
+ a.setInitialValue(n[a.name]);
144
186
  });
145
187
  },
146
- fields: i,
188
+ fields: o,
147
189
  dirtyFields: h,
148
- hasErrors: u,
149
- someTouched: g
190
+ hasErrors: m,
191
+ someTouched: v
150
192
  });
151
193
  }
152
- function M({
153
- fieldName: t,
154
- fieldValue: e,
155
- rules: a,
156
- flush: i
194
+ function B({
195
+ fieldName: e,
196
+ fieldValue: t,
197
+ rules: i,
198
+ flush: o
157
199
  }) {
158
- const o = T(e.value), u = T(!1), g = c(() => (e.value ?? "") !== (o.value ?? "")), h = c(() => u.value ? a.map((r) => ({
159
- fieldName: t,
200
+ const s = w(t.value), m = w(!1), v = c(() => (t.value ?? "") !== (s.value ?? "")), h = c(() => m.value ? i.map((r) => ({
201
+ fieldName: e,
160
202
  ruleName: r.name,
161
- isValid: r.validator(e.value),
162
- message: typeof r.message == "function" ? r.message(e.value) : r.message
203
+ isValid: r.validator(t.value),
204
+ message: typeof r.message == "function" ? r.message(t.value) : r.message
163
205
  })) : []), y = c(
164
206
  () => h.value.filter((r) => !r.isValid).map((r) => ({
165
207
  ruleName: r.ruleName,
166
208
  message: r.message
167
209
  }))
168
210
  );
169
- function m(r = !0) {
170
- i(), u.value = r;
211
+ function g(r = !0) {
212
+ o(), m.value = r;
171
213
  }
172
- function b(r) {
173
- o.value = r;
214
+ function p(r) {
215
+ s.value = r;
174
216
  }
175
- return S({
176
- name: t,
177
- currentValue: N(e),
178
- initialValue: N(o),
179
- isTouched: N(u),
180
- isDirty: N(g),
217
+ return T({
218
+ name: e,
219
+ currentValue: V(t),
220
+ initialValue: V(s),
221
+ isTouched: V(m),
222
+ isDirty: V(v),
181
223
  errorMessage: c(() => {
182
- var r, V;
183
- return ((V = (r = y.value) == null ? void 0 : r[0]) == null ? void 0 : V.message) || "";
224
+ var r, x;
225
+ return ((x = (r = y.value) == null ? void 0 : r[0]) == null ? void 0 : x.message) || "";
184
226
  }),
185
227
  errors: y,
186
- setInitialValue: b,
187
- setTouched: m
228
+ setInitialValue: p,
229
+ setTouched: g
188
230
  });
189
231
  }
190
232
  export {
191
- X as default,
233
+ ee as default,
192
234
  P as email,
193
- v as isDefined,
194
- Y as maxValue,
195
- z as minValue,
196
- G as positiveNumber,
197
- H as price,
198
- J as required,
199
- Q as wholeNumber
235
+ l as isDefined,
236
+ Y as maxLength,
237
+ z as maxValue,
238
+ G as minLength,
239
+ H as minValue,
240
+ J as pattern,
241
+ Q as positiveNumber,
242
+ X as price,
243
+ Z as required,
244
+ W as wholeNumber
200
245
  };
201
246
  //# sourceMappingURL=useValidation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useValidation.js","sources":["../node_modules/flat/index.js","../src/composables/useValidation/ruleFactories/email.ts","../src/composables/useValidation/ruleFactories/maxValue.ts","../src/composables/useValidation/ruleFactories/minValue.ts","../src/composables/useValidation/ruleFactories/positiveNumber.ts","../src/composables/useValidation/ruleFactories/price.ts","../src/composables/useValidation/ruleFactories/required.ts","../src/composables/useValidation/ruleFactories/wholeNumber.ts","../src/composables/useValidation/useValidation.ts"],"sourcesContent":["function isBuffer (obj) {\n return obj &&\n obj.constructor &&\n (typeof obj.constructor.isBuffer === 'function') &&\n obj.constructor.isBuffer(obj)\n}\n\nfunction keyIdentity (key) {\n return key\n}\n\nexport function flatten (target, opts) {\n opts = opts || {}\n\n const delimiter = opts.delimiter || '.'\n const maxDepth = opts.maxDepth\n const transformKey = opts.transformKey || keyIdentity\n const output = {}\n\n function step (object, prev, currentDepth) {\n currentDepth = currentDepth || 1\n Object.keys(object).forEach(function (key) {\n const value = object[key]\n const isarray = opts.safe && Array.isArray(value)\n const type = Object.prototype.toString.call(value)\n const isbuffer = isBuffer(value)\n const isobject = (\n type === '[object Object]' ||\n type === '[object Array]'\n )\n\n const newKey = prev\n ? prev + delimiter + transformKey(key)\n : transformKey(key)\n\n if (!isarray && !isbuffer && isobject && Object.keys(value).length &&\n (!opts.maxDepth || currentDepth < maxDepth)) {\n return step(value, newKey, currentDepth + 1)\n }\n\n output[newKey] = value\n })\n }\n\n step(target)\n\n return output\n}\n\nexport function unflatten (target, opts) {\n opts = opts || {}\n\n const delimiter = opts.delimiter || '.'\n const overwrite = opts.overwrite || false\n const transformKey = opts.transformKey || keyIdentity\n const result = {}\n\n const isbuffer = isBuffer(target)\n if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {\n return target\n }\n\n // safely ensure that the key is\n // an integer.\n function getkey (key) {\n const parsedKey = Number(key)\n\n return (\n isNaN(parsedKey) ||\n key.indexOf('.') !== -1 ||\n opts.object\n )\n ? key\n : parsedKey\n }\n\n function addKeys (keyPrefix, recipient, target) {\n return Object.keys(target).reduce(function (result, key) {\n result[keyPrefix + delimiter + key] = target[key]\n\n return result\n }, recipient)\n }\n\n function isEmpty (val) {\n const type = Object.prototype.toString.call(val)\n const isArray = type === '[object Array]'\n const isObject = type === '[object Object]'\n\n if (!val) {\n return true\n } else if (isArray) {\n return !val.length\n } else if (isObject) {\n return !Object.keys(val).length\n }\n }\n\n target = Object.keys(target).reduce(function (result, key) {\n const type = Object.prototype.toString.call(target[key])\n const isObject = (type === '[object Object]' || type === '[object Array]')\n if (!isObject || isEmpty(target[key])) {\n result[key] = target[key]\n return result\n } else {\n return addKeys(\n key,\n result,\n flatten(target[key], opts)\n )\n }\n }, {})\n\n Object.keys(target).forEach(function (key) {\n const split = key.split(delimiter).map(transformKey)\n let key1 = getkey(split.shift())\n let key2 = getkey(split[0])\n let recipient = result\n\n while (key2 !== undefined) {\n if (key1 === '__proto__') {\n return\n }\n\n const type = Object.prototype.toString.call(recipient[key1])\n const isobject = (\n type === '[object Object]' ||\n type === '[object Array]'\n )\n\n // do not write over falsey, non-undefined values if overwrite is false\n if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') {\n return\n }\n\n if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) {\n recipient[key1] = (\n typeof key2 === 'number' &&\n !opts.object\n ? []\n : {}\n )\n }\n\n recipient = recipient[key1]\n if (split.length > 0) {\n key1 = getkey(split.shift())\n key2 = getkey(split[0])\n }\n }\n\n // unflatten again for 'messy objects'\n recipient[key1] = unflatten(target[key], opts)\n })\n\n return result\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function email(config: Config = {}): ValidationRule {\n return {\n name: 'email',\n validator(value) {\n return !isDefined(value) || (typeof value === 'string' && /^\\S+@\\S+\\.\\S+$/.test(value));\n },\n message: config.message || t('ll.validation.email'),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n max: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n}\n\nexport default function maxValue(config: Config): ValidationRule {\n return {\n name: 'maxValue',\n validator(value) {\n const max = toValue(config.max);\n\n return !isDefined(value) || Number(value) <= max;\n },\n message: config.message || (() => t('ll.validation.maxValue', { max: String(toValue(config.max)) })),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n min: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n}\n\nexport default function minValue(config: Config): ValidationRule {\n return {\n name: 'minValue',\n validator(value) {\n const min = toValue(config.min);\n\n return !isDefined(value) || Number(value) >= min;\n },\n message: config.message || (() => t('ll.validation.minValue', { min: String(toValue(config.min)) })),\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function positiveNumber(config: Config = {}): ValidationRule {\n return {\n name: 'positiveNumber',\n validator(value) {\n return !isDefined(value) || Number(value) > 0;\n },\n message: config.message || t('ll.validation.positiveNumber'),\n };\n}\n","import round from 'lodash-es/round';\n\nimport { DECIMAL_PRECISION } from '../../../constants';\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function price(config: Config = {}): ValidationRule {\n return {\n name: 'price',\n validator(value) {\n const price = Number(value);\n\n return (\n !isDefined(value) || (price !== Infinity && price >= 0 && price === round(price, DECIMAL_PRECISION.CURRENCY))\n );\n },\n message: config.message || t('ll.validation.price'),\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function required(config: Config = {}): ValidationRule {\n return {\n name: 'required',\n validator(value) {\n return isDefined(typeof value === 'string' ? value.trim() : value);\n },\n message: config.message || t('ll.validation.required'),\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function wholeNumber(config: Config = {}): ValidationRule {\n return {\n name: 'wholeNumber',\n validator(value) {\n return !isDefined(value) || (Number.isInteger(Number(value)) && Number(value) >= 0);\n },\n message: config.message || t('ll.validation.wholeNumber'),\n };\n}\n","import { flatten } from 'flat';\nimport debounce from 'lodash-es/debounce';\nimport get from 'lodash-es/get';\nimport { computed, ComputedRef, nextTick, reactive, readonly, Ref, ref, toValue, UnwrapRef, watch } from 'vue';\n\nimport { DEBOUNCE } from '../../constants';\nimport {\n UseValidationArgs,\n ValidationError,\n ValidationField,\n ValidationGroup,\n ValidationRule,\n} from './useValidation.types';\n\nexport default function useValidation<Values extends object>({\n rules,\n values,\n}: UseValidationArgs<Values>): ValidationGroup<Values> {\n const fieldNames = computed(() => Object.keys(flatten(rules, { safe: true })));\n\n const fields = fieldNames.value.reduce((map, fieldName) => {\n const fieldValue = ref(get(toValue(values), fieldName));\n\n // Having this function here allows us to update the fieldValue when the value of the field changes.\n // Also, passing `fieldValue` outside the `.reduce()` loop will cause a racing condition on `fieldValue` updates\n const updateFieldValue = (fieldName: string) => {\n fieldValue.value = get(toValue(values), fieldName);\n };\n\n const debouncedSetFieldValue = debounce(() => {\n updateFieldValue(fieldName);\n }, DEBOUNCE.FAST);\n\n watch(\n () => get(toValue(values), fieldName),\n () => {\n debouncedSetFieldValue();\n },\n );\n\n map[fieldName] = buildField<UnwrapRef<typeof fieldValue>>({\n fieldName,\n fieldValue,\n flush: () => {\n debouncedSetFieldValue.cancel();\n updateFieldValue(fieldName);\n },\n rules: get(rules, fieldName),\n });\n\n return map;\n }, {} as Record<string, ValidationField>);\n\n const fieldList = computed(() => Object.values(fields));\n\n const hasErrors = computed(() => fieldList.value.some((field) => field.errors.length > 0));\n\n const someTouched = computed(() => fieldList.value.some((field) => field.isTouched));\n\n const dirtyFields = computed(() => fieldList.value.filter((field) => field.isDirty));\n\n const validate: ValidationGroup<Values>['validate'] = async function ({ preventScroll } = {}) {\n fieldList.value.forEach((field) => {\n // Doing setTouched(true) on a field that already has isTouched as `true` will not trigger reactivity for that field. Therefore, setting isTouched to `false` for all fields ensures that setTouched(true) will trigger reactivity for every field, which will cause all validations to run and display any error messages.\n field.setTouched(false);\n field.setTouched(true);\n });\n await nextTick();\n\n if (hasErrors.value && !preventScroll) {\n const firstFieldWithError = Object.entries(fields).find(([_, field]) => field.errorMessage);\n const fieldName = firstFieldWithError?.[0] || '';\n const firstErrorElement = document?.querySelector(`[name=${fieldName}]`);\n\n if (firstErrorElement) {\n firstErrorElement.scrollIntoView({ behavior: 'smooth' });\n }\n }\n\n return !hasErrors.value;\n };\n\n const getError: ValidationGroup<Values>['getError'] = function (fieldName: string) {\n return fields[fieldName]?.errorMessage || '';\n };\n\n const touch: ValidationGroup<Values>['touch'] = function (fieldName: string) {\n if (!fields[fieldName]) {\n throw new Error(`In touch: fieldName \"${fieldName}\" does not exist in the validation fields.`);\n }\n\n fields[fieldName].setTouched();\n };\n\n const setAllUntouched: ValidationGroup<Values>['setAllUntouched'] = async function () {\n await nextTick(); // wait for field values to be reset\n fieldList.value.forEach((field) => {\n field.setTouched(false);\n });\n };\n\n const setInitialValues: ValidationGroup<Values>['setInitialValues'] = function (intialValues: Values) {\n fieldList.value.forEach((field) => {\n field.setInitialValue(intialValues[field.name]);\n });\n };\n\n return reactive({\n validate,\n getError,\n touch,\n setAllUntouched,\n setInitialValues,\n fields,\n dirtyFields,\n hasErrors,\n someTouched,\n });\n}\n\ninterface BuildFieldArgs<Value = unknown> {\n fieldName: string;\n fieldValue: ComputedRef<Value>;\n rules: ValidationRule[];\n flush: () => void;\n}\n\nfunction buildField<Value = unknown>({\n fieldName,\n fieldValue,\n rules,\n flush,\n}: BuildFieldArgs<Value>): ValidationField<Value> {\n /**\n * In order for `initialValue` to work properly, the `buildField` function must not be reactive; `buildField` should be called only once for each field when `useValidation` is called.\n */\n const initialValue = ref(fieldValue.value) as Ref<Value>;\n const isTouched = ref(false);\n const isDirty = computed(() => (fieldValue.value ?? '') !== (initialValue.value ?? ''));\n\n const results = computed(() => {\n // Adding a check for `isTouched` to avoid running the validation rules on the initial load, when the field is not touched.\n // if receives a fieldValue with some value as default or not, rule validation should also be triggered only via `touch()` or `validate()` methods.\n if (!isTouched.value) {\n return [];\n }\n\n return rules.map((rule) => ({\n fieldName,\n ruleName: rule.name,\n isValid: rule.validator(fieldValue.value),\n message: typeof rule.message === 'function' ? rule.message(fieldValue.value) : rule.message,\n }));\n });\n\n const errors = computed<ValidationError[]>(() =>\n results.value\n .filter((result) => !result.isValid)\n .map((result) => {\n return {\n ruleName: result.ruleName,\n message: result.message,\n };\n }),\n );\n\n function setTouched(value = true) {\n // Flushing the debounced value to be updated right away.\n // So that, we can have reactivity for `rules` validation, `isTouched`, `isDirty`, among other values\n flush();\n\n isTouched.value = value;\n }\n\n function setInitialValue(value: Value) {\n initialValue.value = value;\n }\n\n return reactive({\n name: fieldName,\n currentValue: readonly(fieldValue),\n initialValue: readonly(initialValue),\n isTouched: readonly(isTouched),\n isDirty: readonly(isDirty),\n errorMessage: computed(() => errors.value?.[0]?.message || ''),\n errors,\n setInitialValue,\n setTouched,\n });\n}\n\n// The ruleFactories are excluded from the main entrypoint in vite.config.ts, so they are exported here instead. This allows one import statement to be used for useValidation, its types, and all of the ruleFactories.\nexport { default as email } from './ruleFactories/email';\nexport { default as maxValue } from './ruleFactories/maxValue';\nexport { default as minValue } from './ruleFactories/minValue';\nexport { default as positiveNumber } from './ruleFactories/positiveNumber';\nexport { default as price } from './ruleFactories/price';\nexport { default as required } from './ruleFactories/required';\nexport { default as wholeNumber } from './ruleFactories/wholeNumber';\nexport * from './useValidation.types';\nexport { default as isDefined } from './utils/isDefined';\n"],"names":["isBuffer","obj","keyIdentity","key","flatten","target","opts","delimiter","maxDepth","transformKey","output","step","object","prev","currentDepth","value","isarray","type","isbuffer","isobject","newKey","email","config","isDefined","t","maxValue","max","toValue","minValue","min","positiveNumber","price","round","DECIMAL_PRECISION","required","wholeNumber","useValidation","rules","values","fields","computed","map","fieldName","fieldValue","ref","get","updateFieldValue","debouncedSetFieldValue","debounce","DEBOUNCE","watch","buildField","fieldList","hasErrors","field","someTouched","dirtyFields","reactive","preventScroll","nextTick","firstFieldWithError","_","firstErrorElement","_a","intialValues","flush","initialValue","isTouched","isDirty","results","rule","errors","result","setTouched","setInitialValue","readonly","_b"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"useValidation.js","sources":["../node_modules/flat/index.js","../src/composables/useValidation/ruleFactories/email.ts","../src/composables/useValidation/ruleFactories/maxLength.ts","../src/composables/useValidation/ruleFactories/maxValue.ts","../src/composables/useValidation/ruleFactories/minLength.ts","../src/composables/useValidation/ruleFactories/minValue.ts","../src/composables/useValidation/ruleFactories/pattern.ts","../src/composables/useValidation/ruleFactories/positiveNumber.ts","../src/composables/useValidation/ruleFactories/price.ts","../src/composables/useValidation/ruleFactories/required.ts","../src/composables/useValidation/ruleFactories/wholeNumber.ts","../src/composables/useValidation/useValidation.ts"],"sourcesContent":["function isBuffer (obj) {\n return obj &&\n obj.constructor &&\n (typeof obj.constructor.isBuffer === 'function') &&\n obj.constructor.isBuffer(obj)\n}\n\nfunction keyIdentity (key) {\n return key\n}\n\nexport function flatten (target, opts) {\n opts = opts || {}\n\n const delimiter = opts.delimiter || '.'\n const maxDepth = opts.maxDepth\n const transformKey = opts.transformKey || keyIdentity\n const output = {}\n\n function step (object, prev, currentDepth) {\n currentDepth = currentDepth || 1\n Object.keys(object).forEach(function (key) {\n const value = object[key]\n const isarray = opts.safe && Array.isArray(value)\n const type = Object.prototype.toString.call(value)\n const isbuffer = isBuffer(value)\n const isobject = (\n type === '[object Object]' ||\n type === '[object Array]'\n )\n\n const newKey = prev\n ? prev + delimiter + transformKey(key)\n : transformKey(key)\n\n if (!isarray && !isbuffer && isobject && Object.keys(value).length &&\n (!opts.maxDepth || currentDepth < maxDepth)) {\n return step(value, newKey, currentDepth + 1)\n }\n\n output[newKey] = value\n })\n }\n\n step(target)\n\n return output\n}\n\nexport function unflatten (target, opts) {\n opts = opts || {}\n\n const delimiter = opts.delimiter || '.'\n const overwrite = opts.overwrite || false\n const transformKey = opts.transformKey || keyIdentity\n const result = {}\n\n const isbuffer = isBuffer(target)\n if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {\n return target\n }\n\n // safely ensure that the key is\n // an integer.\n function getkey (key) {\n const parsedKey = Number(key)\n\n return (\n isNaN(parsedKey) ||\n key.indexOf('.') !== -1 ||\n opts.object\n )\n ? key\n : parsedKey\n }\n\n function addKeys (keyPrefix, recipient, target) {\n return Object.keys(target).reduce(function (result, key) {\n result[keyPrefix + delimiter + key] = target[key]\n\n return result\n }, recipient)\n }\n\n function isEmpty (val) {\n const type = Object.prototype.toString.call(val)\n const isArray = type === '[object Array]'\n const isObject = type === '[object Object]'\n\n if (!val) {\n return true\n } else if (isArray) {\n return !val.length\n } else if (isObject) {\n return !Object.keys(val).length\n }\n }\n\n target = Object.keys(target).reduce(function (result, key) {\n const type = Object.prototype.toString.call(target[key])\n const isObject = (type === '[object Object]' || type === '[object Array]')\n if (!isObject || isEmpty(target[key])) {\n result[key] = target[key]\n return result\n } else {\n return addKeys(\n key,\n result,\n flatten(target[key], opts)\n )\n }\n }, {})\n\n Object.keys(target).forEach(function (key) {\n const split = key.split(delimiter).map(transformKey)\n let key1 = getkey(split.shift())\n let key2 = getkey(split[0])\n let recipient = result\n\n while (key2 !== undefined) {\n if (key1 === '__proto__') {\n return\n }\n\n const type = Object.prototype.toString.call(recipient[key1])\n const isobject = (\n type === '[object Object]' ||\n type === '[object Array]'\n )\n\n // do not write over falsey, non-undefined values if overwrite is false\n if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') {\n return\n }\n\n if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) {\n recipient[key1] = (\n typeof key2 === 'number' &&\n !opts.object\n ? []\n : {}\n )\n }\n\n recipient = recipient[key1]\n if (split.length > 0) {\n key1 = getkey(split.shift())\n key2 = getkey(split[0])\n }\n }\n\n // unflatten again for 'messy objects'\n recipient[key1] = unflatten(target[key], opts)\n })\n\n return result\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function email(config: Config = {}): ValidationRule {\n return {\n name: 'email',\n validator(value) {\n return !isDefined(value) || (typeof value === 'string' && /^\\S+@\\S+\\.\\S+$/.test(value));\n },\n message: config.message || t('ll.validation.email'),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n max: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n trim?: boolean;\n}\n\nexport default function maxLength(config: Config): ValidationRule {\n return {\n name: 'maxLength',\n validator(_value) {\n const max = toValue(config.max);\n const value = toValue(_value);\n\n if (!isDefined(value)) {\n return true;\n }\n\n let valueString = String(value);\n\n if (config.trim) {\n valueString = valueString.trim();\n }\n\n return valueString.length <= max;\n },\n message: config.message || (() => t('ll.validation.maxLength', { max: String(toValue(config.max)) })),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n max: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n}\n\nexport default function maxValue(config: Config): ValidationRule {\n return {\n name: 'maxValue',\n validator(value) {\n const max = toValue(config.max);\n\n return !isDefined(value) || Number(value) <= max;\n },\n message: config.message || (() => t('ll.validation.maxValue', { max: String(toValue(config.max)) })),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n min: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n trim?: boolean;\n}\n\nexport default function minLength(config: Config): ValidationRule {\n return {\n name: 'minLength',\n validator(_value) {\n const min = toValue(config.min);\n const value = toValue(_value);\n\n if (!isDefined(value)) {\n return true;\n }\n\n let valueString = String(value);\n\n if (config.trim) {\n valueString = valueString.trim();\n }\n\n return valueString.length >= min;\n },\n message: config.message || (() => t('ll.validation.minLength', { min: String(toValue(config.min)) })),\n };\n}\n","import { MaybeRefOrGetter, toValue } from 'vue';\n\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n min: MaybeRefOrGetter<number>;\n message?: ValidationMessage;\n}\n\nexport default function minValue(config: Config): ValidationRule {\n return {\n name: 'minValue',\n validator(value) {\n const min = toValue(config.min);\n\n return !isDefined(value) || Number(value) >= min;\n },\n message: config.message || (() => t('ll.validation.minValue', { min: String(toValue(config.min)) })),\n };\n}\n","import { toValue } from 'vue';\n\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n regex: RegExp;\n /** A custom message is required in order to inform the user of the required pattern. */\n message: ValidationMessage;\n}\n\nexport default function pattern(config: Config): ValidationRule {\n return {\n name: 'pattern',\n validator(_value) {\n const value = toValue(_value);\n\n return !isDefined(value) || config.regex.test(String(value));\n },\n message: () => {\n if (typeof config.message !== 'string' || !config.message.trim()) {\n throw new Error(\n 'The \"pattern\" ruleFactory requires a custom message informing the user of the required pattern.',\n );\n }\n\n return config.message;\n },\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function positiveNumber(config: Config = {}): ValidationRule {\n return {\n name: 'positiveNumber',\n validator(value) {\n return !isDefined(value) || Number(value) > 0;\n },\n message: config.message || t('ll.validation.positiveNumber'),\n };\n}\n","import round from 'lodash-es/round';\n\nimport { DECIMAL_PRECISION } from '../../../constants';\nimport { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function price(config: Config = {}): ValidationRule {\n return {\n name: 'price',\n validator(value) {\n const price = Number(value);\n\n return (\n !isDefined(value) || (price !== Infinity && price >= 0 && price === round(price, DECIMAL_PRECISION.CURRENCY))\n );\n },\n message: config.message || t('ll.validation.price'),\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function required(config: Config = {}): ValidationRule {\n return {\n name: 'required',\n validator(value) {\n return isDefined(typeof value === 'string' ? value.trim() : value);\n },\n message: config.message || t('ll.validation.required'),\n };\n}\n","import { t } from '../../../locale';\nimport { ValidationMessage, ValidationRule } from '../useValidation.types';\nimport isDefined from '../utils/isDefined';\n\ninterface Config {\n message?: ValidationMessage;\n}\n\nexport default function wholeNumber(config: Config = {}): ValidationRule {\n return {\n name: 'wholeNumber',\n validator(value) {\n return !isDefined(value) || (Number.isInteger(Number(value)) && Number(value) >= 0);\n },\n message: config.message || t('ll.validation.wholeNumber'),\n };\n}\n","import { flatten } from 'flat';\nimport debounce from 'lodash-es/debounce';\nimport get from 'lodash-es/get';\nimport { computed, ComputedRef, nextTick, reactive, readonly, Ref, ref, toValue, UnwrapRef, watch } from 'vue';\n\nimport { DEBOUNCE } from '../../constants';\nimport {\n UseValidationArgs,\n ValidationError,\n ValidationField,\n ValidationGroup,\n ValidationRule,\n} from './useValidation.types';\n\nexport default function useValidation<Values extends object>({\n rules,\n values,\n}: UseValidationArgs<Values>): ValidationGroup<Values> {\n const fieldNames = computed(() => Object.keys(flatten(rules, { safe: true })));\n\n const fields = fieldNames.value.reduce((map, fieldName) => {\n const fieldValue = ref(get(toValue(values), fieldName));\n\n // Having this function here allows us to update the fieldValue when the value of the field changes.\n // Also, passing `fieldValue` outside the `.reduce()` loop will cause a racing condition on `fieldValue` updates\n const updateFieldValue = (fieldName: string) => {\n fieldValue.value = get(toValue(values), fieldName);\n };\n\n const debouncedSetFieldValue = debounce(() => {\n updateFieldValue(fieldName);\n }, DEBOUNCE.FAST);\n\n watch(\n () => get(toValue(values), fieldName),\n () => {\n debouncedSetFieldValue();\n },\n );\n\n map[fieldName] = buildField<UnwrapRef<typeof fieldValue>>({\n fieldName,\n fieldValue,\n flush: () => {\n debouncedSetFieldValue.cancel();\n updateFieldValue(fieldName);\n },\n rules: get(rules, fieldName),\n });\n\n return map;\n }, {} as Record<string, ValidationField>);\n\n const fieldList = computed(() => Object.values(fields));\n\n const hasErrors = computed(() => fieldList.value.some((field) => field.errors.length > 0));\n\n const someTouched = computed(() => fieldList.value.some((field) => field.isTouched));\n\n const dirtyFields = computed(() => fieldList.value.filter((field) => field.isDirty));\n\n const validate: ValidationGroup<Values>['validate'] = async function ({ preventScroll } = {}) {\n fieldList.value.forEach((field) => {\n // Doing setTouched(true) on a field that already has isTouched as `true` will not trigger reactivity for that field. Therefore, setting isTouched to `false` for all fields ensures that setTouched(true) will trigger reactivity for every field, which will cause all validations to run and display any error messages.\n field.setTouched(false);\n field.setTouched(true);\n });\n await nextTick();\n\n if (hasErrors.value && !preventScroll) {\n const firstFieldWithError = Object.entries(fields).find(([_, field]) => field.errorMessage);\n const fieldName = firstFieldWithError?.[0] || '';\n const firstErrorElement = document?.querySelector(`[name=${fieldName}]`);\n\n if (firstErrorElement) {\n firstErrorElement.scrollIntoView({ behavior: 'smooth' });\n }\n }\n\n return !hasErrors.value;\n };\n\n const getError: ValidationGroup<Values>['getError'] = function (fieldName: string) {\n return fields[fieldName]?.errorMessage || '';\n };\n\n const touch: ValidationGroup<Values>['touch'] = function (fieldName: string) {\n if (!fields[fieldName]) {\n throw new Error(`In touch: fieldName \"${fieldName}\" does not exist in the validation fields.`);\n }\n\n fields[fieldName].setTouched();\n };\n\n const setAllUntouched: ValidationGroup<Values>['setAllUntouched'] = async function () {\n await nextTick(); // wait for field values to be reset\n fieldList.value.forEach((field) => {\n field.setTouched(false);\n });\n };\n\n const setInitialValues: ValidationGroup<Values>['setInitialValues'] = function (intialValues: Values) {\n fieldList.value.forEach((field) => {\n field.setInitialValue(intialValues[field.name]);\n });\n };\n\n return reactive({\n validate,\n getError,\n touch,\n setAllUntouched,\n setInitialValues,\n fields,\n dirtyFields,\n hasErrors,\n someTouched,\n });\n}\n\ninterface BuildFieldArgs<Value = unknown> {\n fieldName: string;\n fieldValue: ComputedRef<Value>;\n rules: ValidationRule[];\n flush: () => void;\n}\n\nfunction buildField<Value = unknown>({\n fieldName,\n fieldValue,\n rules,\n flush,\n}: BuildFieldArgs<Value>): ValidationField<Value> {\n /**\n * In order for `initialValue` to work properly, the `buildField` function must not be reactive; `buildField` should be called only once for each field when `useValidation` is called.\n */\n const initialValue = ref(fieldValue.value) as Ref<Value>;\n const isTouched = ref(false);\n const isDirty = computed(() => (fieldValue.value ?? '') !== (initialValue.value ?? ''));\n\n const results = computed(() => {\n // Adding a check for `isTouched` to avoid running the validation rules on the initial load, when the field is not touched.\n // if receives a fieldValue with some value as default or not, rule validation should also be triggered only via `touch()` or `validate()` methods.\n if (!isTouched.value) {\n return [];\n }\n\n return rules.map((rule) => ({\n fieldName,\n ruleName: rule.name,\n isValid: rule.validator(fieldValue.value),\n message: typeof rule.message === 'function' ? rule.message(fieldValue.value) : rule.message,\n }));\n });\n\n const errors = computed<ValidationError[]>(() =>\n results.value\n .filter((result) => !result.isValid)\n .map((result) => {\n return {\n ruleName: result.ruleName,\n message: result.message,\n };\n }),\n );\n\n function setTouched(value = true) {\n // Flushing the debounced value to be updated right away.\n // So that, we can have reactivity for `rules` validation, `isTouched`, `isDirty`, among other values\n flush();\n\n isTouched.value = value;\n }\n\n function setInitialValue(value: Value) {\n initialValue.value = value;\n }\n\n return reactive({\n name: fieldName,\n currentValue: readonly(fieldValue),\n initialValue: readonly(initialValue),\n isTouched: readonly(isTouched),\n isDirty: readonly(isDirty),\n errorMessage: computed(() => errors.value?.[0]?.message || ''),\n errors,\n setInitialValue,\n setTouched,\n });\n}\n\n// The ruleFactories are excluded from the main entrypoint in vite.config.ts, so they are exported here instead. This allows one import statement to be used for useValidation, its types, and all of the ruleFactories.\nexport { default as email } from './ruleFactories/email';\nexport { default as maxLength } from './ruleFactories/maxLength';\nexport { default as maxValue } from './ruleFactories/maxValue';\nexport { default as minLength } from './ruleFactories/minLength';\nexport { default as minValue } from './ruleFactories/minValue';\nexport { default as pattern } from './ruleFactories/pattern';\nexport { default as positiveNumber } from './ruleFactories/positiveNumber';\nexport { default as price } from './ruleFactories/price';\nexport { default as required } from './ruleFactories/required';\nexport { default as wholeNumber } from './ruleFactories/wholeNumber';\nexport * from './useValidation.types';\nexport { default as isDefined } from './utils/isDefined';\n"],"names":["isBuffer","obj","keyIdentity","key","flatten","target","opts","delimiter","maxDepth","transformKey","output","step","object","prev","currentDepth","value","isarray","type","isbuffer","isobject","newKey","email","config","isDefined","t","maxLength","_value","max","toValue","valueString","maxValue","minLength","min","minValue","pattern","positiveNumber","price","round","DECIMAL_PRECISION","required","wholeNumber","useValidation","rules","values","fields","computed","map","fieldName","fieldValue","ref","get","updateFieldValue","debouncedSetFieldValue","debounce","DEBOUNCE","watch","buildField","fieldList","hasErrors","field","someTouched","dirtyFields","reactive","preventScroll","nextTick","firstFieldWithError","_","firstErrorElement","_a","intialValues","flush","initialValue","isTouched","isDirty","results","rule","errors","result","setTouched","setInitialValue","readonly","_b"],"mappings":"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","x_google_ignoreList":[0]}
@@ -5,27 +5,27 @@ import "lodash-es/get";
5
5
  import "lodash-es/isFinite";
6
6
  import "lodash-es/isPlainObject";
7
7
  import "../constants.js";
8
- const n = "ll";
9
- function m(t, o, a = {}) {
10
- const e = a.global ? "" : `-${location.pathname}`, r = `${n}-${t}${e}`, s = JSON.stringify(o);
8
+ const c = "ll";
9
+ function m(o, r, a = {}) {
10
+ const e = a.global ? "" : `-${location.pathname}`, t = `${c}-${o}${e}`, s = JSON.stringify(r);
11
11
  try {
12
- localStorage.setItem(r, s);
13
- } catch (c) {
14
- c && c.name === "QuotaExceededError" ? l.log(`Your localStorage is full. Failed to save item for key: ${r}`) : l.log(`Failed to save value to localStorage for key: ${r}`);
12
+ localStorage.setItem(t, s);
13
+ } catch (n) {
14
+ (n == null ? void 0 : n.name) === "QuotaExceededError" ? l.log(`Your localStorage is full. Failed to save item for key: ${t}`) : l.log(`Failed to save value to localStorage for key: ${t}`);
15
15
  }
16
16
  }
17
- function g(t, o = {}) {
18
- const a = o.global ? "" : `-${location.pathname}`, e = localStorage.getItem(`${n}-${t}${a}`);
17
+ function g(o, r = {}) {
18
+ const a = r.global ? "" : `-${location.pathname}`, e = localStorage.getItem(`${c}-${o}${a}`);
19
19
  if (e === null || e === "undefined")
20
20
  return null;
21
21
  try {
22
22
  return JSON.parse(e);
23
- } catch (r) {
24
- return l.error(r.message, { error: r }), null;
23
+ } catch (t) {
24
+ return l.error(t == null ? void 0 : t.message, { error: t }), null;
25
25
  }
26
26
  }
27
- function u(t, o = {}) {
28
- const a = o.global ? "" : `-${location.pathname}`, e = `${n}-${t}${a}`;
27
+ function u(o, r = {}) {
28
+ const a = r.global ? "" : `-${location.pathname}`, e = `${c}-${o}${a}`;
29
29
  if (localStorage.getItem(e) !== null)
30
30
  try {
31
31
  localStorage.removeItem(e);
@@ -33,22 +33,22 @@ function u(t, o = {}) {
33
33
  l.error(s.message, { error: s });
34
34
  }
35
35
  }
36
- function y(t, o) {
37
- const a = JSON.parse(localStorage.getItem(t) || "{}");
36
+ function y(o, r) {
37
+ const a = JSON.parse(localStorage.getItem(o) || "{}");
38
38
  try {
39
- return (a[o] || {})[i(location.pathname)];
39
+ return (a[r] || {})[i(location.pathname)];
40
40
  } catch (e) {
41
- l.error(e.message, { error: e });
41
+ l.error(e == null ? void 0 : e.message, { error: e });
42
42
  return;
43
43
  }
44
44
  }
45
- function v(t, o) {
46
- const e = { ...JSON.parse(localStorage.getItem(t) || "{}") };
47
- e[o] && delete e[o][i(location.pathname)];
45
+ function v(o, r) {
46
+ const e = { ...JSON.parse(localStorage.getItem(o) || "{}") };
47
+ e[r] && delete e[r][i(location.pathname)];
48
48
  try {
49
- localStorage.setItem(t, JSON.stringify(e));
50
- } catch (r) {
51
- r && r.name === "QuotaExceededError" ? l.log("Your localStorage is full. Failed to set item.") : l.log("Failed to set item to localStorage.");
49
+ localStorage.setItem(o, JSON.stringify(e));
50
+ } catch (t) {
51
+ (t == null ? void 0 : t.name) === "QuotaExceededError" ? l.log("Your localStorage is full. Failed to set item.") : l.log("Failed to set item to localStorage.");
52
52
  }
53
53
  }
54
54
  const P = {
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sources":["../../src/utils/storage.ts"],"sourcesContent":["import logger from '@leaflink/snitch';\n\nimport { hashCode } from './helpers';\n\nconst PREFIX = 'll';\n\n/**\n * Persist an item to localStorage, unique to each url pathname unless [options.global] is set to true\n *\n * If global is set to false (the default):\n * name: 'foo'\n * data: { a: 'a' }\n *\n * localStorage key: 'll-foo-/c/the-leaf-shop/customers/'\n * localStorage value: { a: 'a' }\n *\n * If global is set to true:\n * name: 'bar'\n * data: { b: 'b' }\n *\n * localStorage key: 'll-bar'\n * localStorage value: { b: 'b' }\n *\n * @param {string} name - the storage key name, often a component name\n * @param {object} data - the data to persist\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n */\nexport function setPersistentItem(name, data, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const storageKey = `${PREFIX}-${name}${scope}`;\n const storageValue = JSON.stringify(data);\n\n try {\n localStorage.setItem(storageKey, storageValue);\n } catch (error: any) {\n if (error && error.name === 'QuotaExceededError') {\n logger.log(`Your localStorage is full. Failed to save item for key: ${storageKey}`);\n } else {\n logger.log(`Failed to save value to localStorage for key: ${storageKey}`);\n }\n }\n}\n\n/**\n * Retrieve an item from localStorage, previously saved by `setPersistentItem`.\n * @param {string} name The storage key name, often a component name\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n * @returns {any | undefined}\n */\nexport function getPersistentItem(name, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const item = localStorage.getItem(`${PREFIX}-${name}${scope}`);\n\n // localStorage.getItem always returns a string or null. When it's a string,\n // it usually contains an object or a boolean. If the value is 'false', we\n // need to ensure we return false instead of null.\n if (item === null || item === 'undefined') {\n return null;\n }\n\n try {\n return JSON.parse(item);\n } catch (err) {\n logger.error((err as Error).message, { error: err });\n\n return null;\n }\n}\n\n/**\n * Remove an item from localStorage, previously saved by `setPersistentItem`.\n * @param {string} name The storage key name, often a component name\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n */\nexport function removePersistentItem(name, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const storageKey = `${PREFIX}-${name}${scope}`;\n const item = localStorage.getItem(storageKey);\n\n if (item === null) {\n return;\n }\n\n try {\n localStorage.removeItem(storageKey);\n } catch (err) {\n logger.error((err as Error).message, { error: err });\n }\n}\n\n/**\n ***************** DEPRECATED *****************\n */\nexport function getPersistentItem__deprecated(itemKey: string, name) {\n const item = JSON.parse(localStorage.getItem(itemKey) || '{}');\n\n try {\n return (item[name] || {})[hashCode(location.pathname)];\n } catch (err) {\n logger.error((err as Error).message, { error: err });\n\n return undefined;\n }\n}\n\nexport function removePersistentItem__deprecated(itemKey, name) {\n const item = JSON.parse(localStorage.getItem(itemKey) || '{}');\n const itemValue = { ...item };\n\n if (itemValue[name]) {\n delete itemValue[name][hashCode(location.pathname)];\n }\n\n try {\n localStorage.setItem(itemKey, JSON.stringify(itemValue));\n } catch (error: any) {\n if (error && error.name === 'QuotaExceededError') {\n logger.log(`Your localStorage is full. Failed to set item.`);\n } else {\n logger.log(`Failed to set item to localStorage.`);\n }\n }\n}\n// END DEPRECATED\n\nexport const persistentStorage = {\n setItem: setPersistentItem,\n getItem: getPersistentItem,\n removeItem: removePersistentItem,\n};\n"],"names":["PREFIX","setPersistentItem","name","data","options","scope","storageKey","storageValue","error","logger","getPersistentItem","item","err","removePersistentItem","getPersistentItem__deprecated","itemKey","hashCode","removePersistentItem__deprecated","itemValue","persistentStorage"],"mappings":";;;;;;;AAIA,MAAMA,IAAS;AAwBR,SAASC,EAAkBC,GAAMC,GAAMC,IAAgC,CAAA,GAAI;AAChF,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDE,IAAa,GAAGN,CAAM,IAAIE,CAAI,GAAGG,CAAK,IACtCE,IAAe,KAAK,UAAUJ,CAAI;AAEpC,MAAA;AACW,iBAAA,QAAQG,GAAYC,CAAY;AAAA,WACtCC,GAAY;AACf,IAAAA,KAASA,EAAM,SAAS,uBACnBC,EAAA,IAAI,2DAA2DH,CAAU,EAAE,IAE3EG,EAAA,IAAI,iDAAiDH,CAAU,EAAE;AAAA,EAE5E;AACF;AASO,SAASI,EAAkBR,GAAME,IAAgC,IAAI;AAC1E,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDO,IAAO,aAAa,QAAQ,GAAGX,CAAM,IAAIE,CAAI,GAAGG,CAAK,EAAE;AAKzD,MAAAM,MAAS,QAAQA,MAAS;AACrB,WAAA;AAGL,MAAA;AACK,WAAA,KAAK,MAAMA,CAAI;AAAA,WACfC,GAAK;AACZ,WAAAH,EAAO,MAAOG,EAAc,SAAS,EAAE,OAAOA,GAAK,GAE5C;AAAA,EACT;AACF;AAQO,SAASC,EAAqBX,GAAME,IAAgC,IAAI;AAC7E,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDE,IAAa,GAAGN,CAAM,IAAIE,CAAI,GAAGG,CAAK;AAG5C,MAFa,aAAa,QAAQC,CAAU,MAE/B;AAIT,QAAA;AACF,mBAAa,WAAWA,CAAU;AAAA,aAC3BM,GAAK;AACZ,MAAAH,EAAO,MAAOG,EAAc,SAAS,EAAE,OAAOA,GAAK;AAAA,IACrD;AACF;AAKgB,SAAAE,EAA8BC,GAAiBb,GAAM;AACnE,QAAMS,IAAO,KAAK,MAAM,aAAa,QAAQI,CAAO,KAAK,IAAI;AAEzD,MAAA;AACM,YAAAJ,EAAKT,CAAI,KAAK,CAAA,GAAIc,EAAS,SAAS,QAAQ,CAAC;AAAA,WAC9CJ,GAAK;AACZ,IAAAH,EAAO,MAAOG,EAAc,SAAS,EAAE,OAAOA,GAAK;AAE5C;AAAA,EACT;AACF;AAEgB,SAAAK,EAAiCF,GAASb,GAAM;AAExD,QAAAgB,IAAY,EAAE,GADP,KAAK,MAAM,aAAa,QAAQH,CAAO,KAAK,IAAI;AAGzD,EAAAG,EAAUhB,CAAI,KAChB,OAAOgB,EAAUhB,CAAI,EAAEc,EAAS,SAAS,QAAQ,CAAC;AAGhD,MAAA;AACF,iBAAa,QAAQD,GAAS,KAAK,UAAUG,CAAS,CAAC;AAAA,WAChDV,GAAY;AACf,IAAAA,KAASA,EAAM,SAAS,uBAC1BC,EAAO,IAAI,gDAAgD,IAE3DA,EAAO,IAAI,qCAAqC;AAAA,EAEpD;AACF;AAGO,MAAMU,IAAoB;AAAA,EAC/B,SAASlB;AAAA,EACT,SAASS;AAAA,EACT,YAAYG;AACd;"}
1
+ {"version":3,"file":"storage.js","sources":["../../src/utils/storage.ts"],"sourcesContent":["import logger from '@leaflink/snitch';\n\nimport { hashCode } from './helpers';\n\nconst PREFIX = 'll';\n\n/**\n * Persist an item to localStorage, unique to each url pathname unless [options.global] is set to true\n *\n * If global is set to false (the default):\n * name: 'foo'\n * data: { a: 'a' }\n *\n * localStorage key: 'll-foo-/c/the-leaf-shop/customers/'\n * localStorage value: { a: 'a' }\n *\n * If global is set to true:\n * name: 'bar'\n * data: { b: 'b' }\n *\n * localStorage key: 'll-bar'\n * localStorage value: { b: 'b' }\n *\n * @param {string} name - the storage key name, often a component name\n * @param {object} data - the data to persist\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n */\nexport function setPersistentItem(name, data, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const storageKey = `${PREFIX}-${name}${scope}`;\n const storageValue = JSON.stringify(data);\n\n try {\n localStorage.setItem(storageKey, storageValue);\n } catch (error) {\n if ((error as Error)?.name === 'QuotaExceededError') {\n logger.log(`Your localStorage is full. Failed to save item for key: ${storageKey}`);\n } else {\n logger.log(`Failed to save value to localStorage for key: ${storageKey}`);\n }\n }\n}\n\n/**\n * Retrieve an item from localStorage, previously saved by `setPersistentItem`.\n * @param {string} name The storage key name, often a component name\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n * @returns {any | undefined}\n */\nexport function getPersistentItem(name, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const item = localStorage.getItem(`${PREFIX}-${name}${scope}`);\n\n // localStorage.getItem always returns a string or null. When it's a string,\n // it usually contains an object or a boolean. If the value is 'false', we\n // need to ensure we return false instead of null.\n if (item === null || item === 'undefined') {\n return null;\n }\n\n try {\n return JSON.parse(item);\n } catch (err) {\n logger.error((err as Error)?.message, { error: err });\n\n return null;\n }\n}\n\n/**\n * Remove an item from localStorage, previously saved by `setPersistentItem`.\n * @param {string} name The storage key name, often a component name\n * @param {object} [options] - an optional options object\n * @param {boolean} [options.global] - does not add url to the key when true\n */\nexport function removePersistentItem(name, options: { global?: boolean } = {}) {\n const scope = options.global ? '' : `-${location.pathname}`;\n const storageKey = `${PREFIX}-${name}${scope}`;\n const item = localStorage.getItem(storageKey);\n\n if (item === null) {\n return;\n }\n\n try {\n localStorage.removeItem(storageKey);\n } catch (err) {\n logger.error((err as Error).message, { error: err });\n }\n}\n\n/**\n ***************** DEPRECATED *****************\n */\nexport function getPersistentItem__deprecated(itemKey: string, name) {\n const item = JSON.parse(localStorage.getItem(itemKey) || '{}');\n\n try {\n return (item[name] || {})[hashCode(location.pathname)];\n } catch (err) {\n logger.error((err as Error)?.message, { error: err });\n\n return undefined;\n }\n}\n\nexport function removePersistentItem__deprecated(itemKey, name) {\n const item = JSON.parse(localStorage.getItem(itemKey) || '{}');\n const itemValue = { ...item };\n\n if (itemValue[name]) {\n delete itemValue[name][hashCode(location.pathname)];\n }\n\n try {\n localStorage.setItem(itemKey, JSON.stringify(itemValue));\n } catch (error) {\n if ((error as Error)?.name === 'QuotaExceededError') {\n logger.log(`Your localStorage is full. Failed to set item.`);\n } else {\n logger.log(`Failed to set item to localStorage.`);\n }\n }\n}\n// END DEPRECATED\n\nexport const persistentStorage = {\n setItem: setPersistentItem,\n getItem: getPersistentItem,\n removeItem: removePersistentItem,\n};\n"],"names":["PREFIX","setPersistentItem","name","data","options","scope","storageKey","storageValue","error","logger","getPersistentItem","item","err","removePersistentItem","getPersistentItem__deprecated","itemKey","hashCode","removePersistentItem__deprecated","itemValue","persistentStorage"],"mappings":";;;;;;;AAIA,MAAMA,IAAS;AAwBR,SAASC,EAAkBC,GAAMC,GAAMC,IAAgC,CAAA,GAAI;AAChF,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDE,IAAa,GAAGN,CAAM,IAAIE,CAAI,GAAGG,CAAK,IACtCE,IAAe,KAAK,UAAUJ,CAAI;AAEpC,MAAA;AACW,iBAAA,QAAQG,GAAYC,CAAY;AAAA,WACtCC,GAAO;AACT,KAAAA,KAAA,gBAAAA,EAAiB,UAAS,uBACtBC,EAAA,IAAI,2DAA2DH,CAAU,EAAE,IAE3EG,EAAA,IAAI,iDAAiDH,CAAU,EAAE;AAAA,EAE5E;AACF;AASO,SAASI,EAAkBR,GAAME,IAAgC,IAAI;AAC1E,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDO,IAAO,aAAa,QAAQ,GAAGX,CAAM,IAAIE,CAAI,GAAGG,CAAK,EAAE;AAKzD,MAAAM,MAAS,QAAQA,MAAS;AACrB,WAAA;AAGL,MAAA;AACK,WAAA,KAAK,MAAMA,CAAI;AAAA,WACfC,GAAK;AACZ,WAAAH,EAAO,MAAOG,KAAA,gBAAAA,EAAe,SAAS,EAAE,OAAOA,GAAK,GAE7C;AAAA,EACT;AACF;AAQO,SAASC,EAAqBX,GAAME,IAAgC,IAAI;AAC7E,QAAMC,IAAQD,EAAQ,SAAS,KAAK,IAAI,SAAS,QAAQ,IACnDE,IAAa,GAAGN,CAAM,IAAIE,CAAI,GAAGG,CAAK;AAG5C,MAFa,aAAa,QAAQC,CAAU,MAE/B;AAIT,QAAA;AACF,mBAAa,WAAWA,CAAU;AAAA,aAC3BM,GAAK;AACZ,MAAAH,EAAO,MAAOG,EAAc,SAAS,EAAE,OAAOA,GAAK;AAAA,IACrD;AACF;AAKgB,SAAAE,EAA8BC,GAAiBb,GAAM;AACnE,QAAMS,IAAO,KAAK,MAAM,aAAa,QAAQI,CAAO,KAAK,IAAI;AAEzD,MAAA;AACM,YAAAJ,EAAKT,CAAI,KAAK,CAAA,GAAIc,EAAS,SAAS,QAAQ,CAAC;AAAA,WAC9CJ,GAAK;AACZ,IAAAH,EAAO,MAAOG,KAAA,gBAAAA,EAAe,SAAS,EAAE,OAAOA,GAAK;AAE7C;AAAA,EACT;AACF;AAEgB,SAAAK,EAAiCF,GAASb,GAAM;AAExD,QAAAgB,IAAY,EAAE,GADP,KAAK,MAAM,aAAa,QAAQH,CAAO,KAAK,IAAI;AAGzD,EAAAG,EAAUhB,CAAI,KAChB,OAAOgB,EAAUhB,CAAI,EAAEc,EAAS,SAAS,QAAQ,CAAC;AAGhD,MAAA;AACF,iBAAa,QAAQD,GAAS,KAAK,UAAUG,CAAS,CAAC;AAAA,WAChDV,GAAO;AACT,KAAAA,KAAA,gBAAAA,EAAiB,UAAS,uBAC7BC,EAAO,IAAI,gDAAgD,IAE3DA,EAAO,IAAI,qCAAqC;AAAA,EAEpD;AACF;AAGO,MAAMU,IAAoB;AAAA,EAC/B,SAASlB;AAAA,EACT,SAASS;AAAA,EACT,YAAYG;AACd;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leaflink/stash",
3
- "version": "44.6.0",
3
+ "version": "44.6.1",
4
4
  "description": "LeafLink's design system.",
5
5
  "homepage": "https://stash.leaflink.com",
6
6
  "main": "./dist/index.ts",