@leaflink/stash 53.4.6 → 53.4.8
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.
- package/dist/AppSidebar.js +56 -52
- package/dist/AppSidebar.js.map +1 -1
- package/dist/AppTopbar.js +1 -1
- package/dist/Copy.js +1 -1
- package/dist/DataViewFilters.js +1 -1
- package/dist/DataViewFilters.js.map +1 -1
- package/dist/DataViewToolbar.js +139 -125
- package/dist/DataViewToolbar.js.map +1 -1
- package/dist/DatePicker.js +1114 -1113
- package/dist/DatePicker.js.map +1 -1
- package/dist/Modal.js +105 -89
- package/dist/Modal.js.map +1 -1
- package/dist/Modals.js +30 -26
- package/dist/Modals.js.map +1 -1
- package/dist/MoreActions.js +294 -288
- package/dist/MoreActions.js.map +1 -1
- package/dist/PageNavigation.js +1 -1
- package/dist/RadioGroup.js +69 -62
- package/dist/RadioGroup.js.map +1 -1
- package/dist/SearchBar.js +27 -25
- package/dist/SearchBar.js.map +1 -1
- package/dist/Select.js +103 -101
- package/dist/Select.js.map +1 -1
- package/dist/Stepper.js +1 -1
- package/dist/Tab.js +1 -1
- package/dist/Table.js +1 -1
- package/dist/Tabs.js +2 -2
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-DEopbeSY.js +131 -0
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-DEopbeSY.js.map +1 -0
- package/dist/Thumbnail.js +42 -42
- package/dist/Thumbnail.js.map +1 -1
- package/dist/ThumbnailGroup.js +24 -22
- package/dist/ThumbnailGroup.js.map +1 -1
- package/dist/Timeline.js +15 -13
- package/dist/Timeline.js.map +1 -1
- package/dist/Toast.vue.d.ts +1 -1
- package/dist/Tooltip.js +1 -1
- package/dist/{Tooltip.vue_vue_type_script_setup_true_lang-CFpM7Ldj.js → Tooltip.vue_vue_type_script_setup_true_lang-UUjw5O1x.js} +2 -2
- package/dist/{Tooltip.vue_vue_type_script_setup_true_lang-CFpM7Ldj.js.map → Tooltip.vue_vue_type_script_setup_true_lang-UUjw5O1x.js.map} +1 -1
- package/dist/components.css +1 -1
- package/dist/getContrastingTextColor.d.ts +8 -0
- package/dist/index-t9tXBnql.js +469 -0
- package/dist/{index-DA70nQCT.js.map → index-t9tXBnql.js.map} +1 -1
- package/dist/templateRefNarrowing-CeANDylX.js +22 -0
- package/dist/templateRefNarrowing-CeANDylX.js.map +1 -0
- package/dist/useMediaQuery.d.ts +12 -10
- package/dist/useMediaQuery.js +7 -29
- package/dist/useMediaQuery.js.map +1 -1
- package/dist/useSortable.js +1 -1
- package/dist/useValidation.d.ts +11 -1
- package/dist/useValidation.js +240 -198
- package/dist/useValidation.js.map +1 -1
- package/dist/utils/getContrastingTextColor.js +36 -24
- package/dist/utils/getContrastingTextColor.js.map +1 -1
- package/package.json +1 -2
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-B3FBaVP5.js +0 -130
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-B3FBaVP5.js.map +0 -1
- package/dist/index-DA70nQCT.js +0 -424
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useValidation.js","sources":["../../../node_modules/.pnpm/flat@6.0.1/node_modules/flat/index.js","../src/composables/useValidation/parseJsonApiFieldErrors.ts","../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 type { JsonApiValidationError } from './useValidation.types';\n\n/**\n * Converts a JSON:API pointer (e.g. `/data/attributes/email` or `/data/attributes/product_name`) to a flat field name\n * for useValidation. Segment names are left unchanged (e.g. snake_case from the backend stays snake_case). Nested\n * paths (e.g. `/data/attributes/price/min_value`) become dotted names (e.g. `price.min_value`).\n */\nfunction pointerToFieldName(pointer: string): string {\n const normalized = pointer.replace(/^\\//, '');\n const prefix = 'data/attributes/';\n\n if (normalized.startsWith(prefix)) {\n const pathWithinAttributes = normalized.slice(prefix.length);\n const segments = pathWithinAttributes.split('/').filter(Boolean);\n return segments.join('.');\n }\n\n const segments = normalized.split('/').filter(Boolean);\n return segments[segments.length - 1] || pointer;\n}\n\n/**\n * Parses an array of JSON:API error objects into a map of field names to error messages.\n * Uses `source.pointer` to determine the field (e.g. `/data/attributes/email` → `email`) and `detail` (or `title`) as the message.\n * If multiple errors reference the same field, the last one wins.\n */\nexport function parseJsonApiFieldErrors(errors: JsonApiValidationError[]): Record<string, string> {\n const map: Record<string, string> = {};\n for (const err of errors) {\n const pointer = err.source?.pointer;\n if (!pointer) {\n continue;\n }\n const message = err.detail || err.title || '';\n if (!message) {\n continue;\n }\n const fieldName = pointerToFieldName(pointer);\n map[fieldName] = message;\n }\n return map;\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, nextTick, reactive, readonly, Ref, ref, toValue, UnwrapRef, watch } from 'vue';\n\nimport { DEBOUNCE } from '../../constants';\nimport { parseJsonApiFieldErrors } from './parseJsonApiFieldErrors';\nimport {\n type JsonApiValidationError,\n UseValidationArgs,\n ValidationError,\n ValidationField,\n ValidationGroup,\n ValidationRule,\n} from './useValidation.types';\n\nconst API_ERROR_RULE_NAME = 'api';\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 const apiErrors = ref<Record<string, string>>({});\n\n const fields = fieldNames.value.reduce(\n (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 getApiError: () => apiErrors.value[fieldName] || '',\n rules: get(rules, fieldName),\n });\n\n return map;\n },\n {} as Record<string, ValidationField>,\n );\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 function setApiErrors(errors: JsonApiValidationError[]) {\n const parsed = parseJsonApiFieldErrors(errors);\n const known = fieldNames.value;\n const next: Record<string, string> = {};\n for (const name of known) {\n if (parsed[name]) {\n next[name] = parsed[name];\n }\n }\n apiErrors.value = next;\n }\n\n function clearApiErrors(fieldName?: string) {\n if (fieldName) {\n const next = { ...apiErrors.value };\n delete next[fieldName];\n apiErrors.value = next;\n } else {\n apiErrors.value = {};\n }\n }\n\n return reactive({\n validate,\n getError,\n touch,\n setAllUntouched,\n setInitialValues,\n setApiErrors,\n clearApiErrors,\n fields,\n dirtyFields,\n hasErrors,\n someTouched,\n });\n}\n\ninterface BuildFieldArgs<Value = unknown> {\n fieldName: string;\n fieldValue: Ref<Value> | Ref<Value>;\n rules: ValidationRule[];\n flush: () => void;\n getApiError: () => string;\n}\n\nfunction buildField<Value = unknown>({\n fieldName,\n fieldValue,\n rules,\n flush,\n getApiError,\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 const apiMessage = getApiError();\n const apiErrorList: ValidationError[] =\n apiMessage !== '' ? [{ ruleName: API_ERROR_RULE_NAME, message: apiMessage }] : [];\n const ruleErrors = results.value\n .filter((result) => !result.isValid)\n .map((result) => ({\n ruleName: result.ruleName,\n message: result.message,\n }));\n return [...apiErrorList, ...ruleErrors];\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","pointerToFieldName","pointer","normalized","prefix","segments","parseJsonApiFieldErrors","errors","map","err","_a","message","fieldName","email","config","isDefined","t","maxLength","_value","max","toValue","valueString","maxValue","minLength","min","minValue","pattern","positiveNumber","price","round","DECIMAL_PRECISION","required","wholeNumber","API_ERROR_RULE_NAME","useValidation","rules","values","fieldNames","computed","apiErrors","ref","fields","fieldValue","get","updateFieldValue","debouncedSetFieldValue","debounce","DEBOUNCE","watch","buildField","fieldList","hasErrors","field","someTouched","dirtyFields","validate","preventScroll","nextTick","firstFieldWithError","firstErrorElement","getError","touch","setAllUntouched","setInitialValues","intialValues","setApiErrors","parsed","known","next","name","clearApiErrors","reactive","flush","getApiError","initialValue","isTouched","isDirty","results","rule","apiMessage","apiErrorList","ruleErrors","result","setTouched","setInitialValue","readonly","_b"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"useValidation.js","sources":["../src/composables/useValidation/parseJsonApiFieldErrors.ts","../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":["import type { JsonApiValidationError } from './useValidation.types';\n\n/**\n * Converts a JSON:API pointer to a dotted field name for useValidation.\n *\n * - Standard attributes: `/data/attributes/...` → strip that prefix, then join segments with `.` (e.g. `email`,\n * `price.min_value`, `terpenes.0.name`). Segment names are left unchanged (e.g. snake_case stays snake_case).\n * - Shorthand paths (no `data/attributes/`): join all segments with `.` (e.g. `/terpenes/0/percentage` →\n * `terpenes.0.percentage`). Single-segment pointers (e.g. `/email`) still map to `email`.\n */\nfunction pointerToFieldName(pointer: string): string {\n const normalized = pointer.replace(/^\\//, '');\n const prefix = 'data/attributes/';\n\n if (normalized.startsWith(prefix)) {\n const pathWithinAttributes = normalized.slice(prefix.length);\n const segments = pathWithinAttributes.split('/').filter(Boolean);\n return segments.join('.');\n }\n\n const segments = normalized.split('/').filter(Boolean);\n return segments.length ? segments.join('.') : pointer;\n}\n\n/**\n * Parses an array of JSON:API error objects into a map of field names to error messages.\n * Uses `source.pointer` to determine the field (e.g. `/data/attributes/email` → `email`) and `detail` (or `title`) as the message.\n * If multiple errors reference the same field, the last one wins.\n */\nexport function parseJsonApiFieldErrors(errors: JsonApiValidationError[]): Record<string, string> {\n const map: Record<string, string> = {};\n for (const err of errors) {\n const pointer = err.source?.pointer;\n if (!pointer) {\n continue;\n }\n const message = err.detail || err.title || '';\n if (!message) {\n continue;\n }\n const fieldName = pointerToFieldName(pointer);\n map[fieldName] = message;\n }\n return map;\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 debounce from 'lodash-es/debounce';\nimport get from 'lodash-es/get';\nimport {\n computed,\n effectScope,\n nextTick,\n reactive,\n readonly,\n type Ref,\n ref,\n toValue,\n type UnwrapRef,\n watch,\n} from 'vue';\n\nimport { DEBOUNCE } from '../../constants';\nimport { parseJsonApiFieldErrors } from './parseJsonApiFieldErrors';\nimport type {\n JsonApiValidationError,\n UseValidationArgs,\n ValidationError,\n ValidationField,\n ValidationGroup,\n ValidationRule,\n} from './useValidation.types';\n\nconst API_ERROR_RULE_NAME = 'api';\n\nfunction isValidationRule(x: unknown): x is ValidationRule {\n if (typeof x !== 'object' || x === null) {\n return false;\n }\n if (!('validator' in x)) {\n return false;\n }\n return typeof Reflect.get(x, 'validator') === 'function';\n}\n\nfunction isValidationRuleArray(value: unknown): value is ValidationRule[] {\n return Array.isArray(value) && value.every(isValidationRule);\n}\n\n/**\n * Lists dotted field paths for useValidation. Unlike `flatten(..., { safe: true })`, this descends into\n * arrays whose elements are per-row rule objects (e.g. `terpenes: [{ name: [...], amount: [...] }]`).\n * Arrays whose first element looks like a `ValidationRule` are treated as a single field's rule list.\n * An empty rule array at a path (e.g. `optionalField: []`) still registers that field so `touch`, API\n * errors, and dirty state work.\n */\nfunction collectValidationFieldPaths(value: unknown, prefix = ''): string[] {\n if (value === null || typeof value !== 'object') {\n return [];\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return prefix ? [prefix] : [];\n }\n const first = value[0];\n if (isValidationRule(first)) {\n return prefix ? [prefix] : [];\n }\n const paths: string[] = [];\n for (let i = 0; i < value.length; i++) {\n const p = prefix === '' ? String(i) : `${prefix}.${i}`;\n paths.push(...collectValidationFieldPaths(value[i], p));\n }\n return paths;\n }\n\n const paths: string[] = [];\n for (const key of Object.keys(value)) {\n const child = (value as Record<string, unknown>)[key];\n const p = prefix === '' ? key : `${prefix}.${key}`;\n paths.push(...collectValidationFieldPaths(child, p));\n }\n return paths;\n}\n\n/** Per-field teardown: value watcher, debounce, and `buildField` effectScope (stops its computeds). */\ninterface FieldCleanup {\n stop: () => void;\n cancelDebounced: () => void;\n stopFieldScope: () => void;\n}\n\nexport default function useValidation<Values extends object>({\n rules,\n values,\n}: UseValidationArgs<Values>): ValidationGroup<Values> {\n const apiErrors = ref<Record<string, string>>({});\n\n const fields = reactive<Record<string, ValidationField>>({});\n const fieldCleanups = new Map<string, FieldCleanup>();\n\n // Sort so traversal order is stable; the computed caches one sorted list per rules invalidation.\n const sortedRuleFieldNames = computed(() => collectValidationFieldPaths(toValue(rules)).sort());\n\n function removeField(fieldName: string) {\n const cleanup = fieldCleanups.get(fieldName);\n if (cleanup) {\n cleanup.cancelDebounced();\n cleanup.stop();\n cleanup.stopFieldScope();\n fieldCleanups.delete(fieldName);\n }\n if (fields[fieldName]) {\n delete fields[fieldName];\n }\n if (apiErrors.value[fieldName]) {\n const next = { ...apiErrors.value };\n delete next[fieldName];\n apiErrors.value = next;\n }\n }\n\n function addField(fieldName: string) {\n if (fields[fieldName]) {\n return;\n }\n\n const fieldValue = ref(get(toValue(values), fieldName));\n\n const updateFieldValue = () => {\n fieldValue.value = get(toValue(values), fieldName);\n };\n\n const debouncedSetFieldValue = debounce(() => {\n updateFieldValue();\n }, DEBOUNCE.FAST);\n\n const stop = watch(\n () => get(toValue(values), fieldName),\n () => {\n debouncedSetFieldValue();\n },\n );\n\n // Computeds inside `buildField` subscribe to rules/apiErrors; scope.stop() drops those subscriptions when the row is removed.\n const fieldScope = effectScope();\n const builtField = fieldScope.run(() =>\n buildField<UnwrapRef<typeof fieldValue>>({\n fieldName,\n fieldValue,\n flush: () => {\n debouncedSetFieldValue.cancel();\n updateFieldValue();\n },\n getApiError: () => apiErrors.value[fieldName] || '',\n getRules: () => {\n const raw = get(toValue(rules), fieldName);\n return isValidationRuleArray(raw) ? raw : [];\n },\n }),\n );\n\n if (!builtField) {\n stop();\n debouncedSetFieldValue.cancel();\n fieldScope.stop();\n return;\n }\n\n fieldCleanups.set(fieldName, {\n stop,\n cancelDebounced: () => debouncedSetFieldValue.cancel(),\n stopFieldScope: () => fieldScope.stop(),\n });\n\n fields[fieldName] = builtField;\n }\n\n watch(\n sortedRuleFieldNames,\n (newNames, oldNames) => {\n const prev = oldNames ?? [];\n const newSet = new Set(newNames);\n const oldSet = new Set(prev);\n\n for (const name of prev) {\n if (!newSet.has(name)) {\n removeField(name);\n }\n }\n for (const name of newNames) {\n if (!oldSet.has(name)) {\n addField(name);\n }\n }\n },\n { immediate: true },\n );\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 (initialValues: Values) {\n fieldList.value.forEach((field) => {\n field.setInitialValue(get(initialValues, field.name));\n });\n };\n\n function setApiErrors(errors: JsonApiValidationError[]) {\n const parsed = parseJsonApiFieldErrors(errors);\n const known = sortedRuleFieldNames.value;\n const next: Record<string, string> = {};\n for (const name of known) {\n if (parsed[name]) {\n next[name] = parsed[name];\n }\n }\n apiErrors.value = next;\n }\n\n function clearApiErrors(fieldName?: string) {\n if (fieldName) {\n const next = { ...apiErrors.value };\n delete next[fieldName];\n apiErrors.value = next;\n } else {\n apiErrors.value = {};\n }\n }\n\n return reactive({\n validate,\n getError,\n touch,\n setAllUntouched,\n setInitialValues,\n setApiErrors,\n clearApiErrors,\n fields,\n dirtyFields,\n hasErrors,\n someTouched,\n });\n}\n\ninterface BuildFieldArgs<Value = unknown> {\n fieldName: string;\n fieldValue: Ref<Value>;\n getRules: () => ValidationRule[];\n flush: () => void;\n getApiError: () => string;\n}\n\nfunction buildField<Value = unknown>({\n fieldName,\n fieldValue,\n getRules,\n flush,\n getApiError,\n}: BuildFieldArgs<Value>): ValidationField<Value> {\n /**\n * In order for `initialValue` to work properly, `initialValue` is captured when the field is registered; `setInitialValue` updates it thereafter.\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 const rulesList = getRules();\n return rulesList.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 const apiMessage = getApiError();\n const apiErrorList: ValidationError[] =\n apiMessage !== '' ? [{ ruleName: API_ERROR_RULE_NAME, message: apiMessage }] : [];\n const ruleErrors = results.value\n .filter((result) => !result.isValid)\n .map((result) => ({\n ruleName: result.ruleName,\n message: result.message,\n }));\n return [...apiErrorList, ...ruleErrors];\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":["pointerToFieldName","pointer","normalized","prefix","segments","parseJsonApiFieldErrors","errors","map","err","_a","message","fieldName","email","config","value","isDefined","t","maxLength","_value","max","toValue","valueString","maxValue","minLength","min","minValue","pattern","positiveNumber","price","round","DECIMAL_PRECISION","required","wholeNumber","API_ERROR_RULE_NAME","isValidationRule","x","isValidationRuleArray","collectValidationFieldPaths","first","paths","i","p","key","child","useValidation","rules","values","apiErrors","ref","fields","reactive","fieldCleanups","sortedRuleFieldNames","computed","removeField","cleanup","next","addField","fieldValue","get","updateFieldValue","debouncedSetFieldValue","debounce","DEBOUNCE","stop","watch","fieldScope","effectScope","builtField","buildField","raw","newNames","oldNames","prev","newSet","oldSet","name","fieldList","hasErrors","field","someTouched","dirtyFields","validate","preventScroll","nextTick","firstFieldWithError","firstErrorElement","getError","touch","setAllUntouched","setInitialValues","initialValues","setApiErrors","parsed","known","clearApiErrors","getRules","flush","getApiError","initialValue","isTouched","isDirty","results","rule","apiMessage","apiErrorList","ruleErrors","result","setTouched","setInitialValue","readonly","_b"],"mappings":"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"}
|
|
@@ -1,40 +1,52 @@
|
|
|
1
1
|
import { S as g } from "../colors-DDDVvqfQ.js";
|
|
2
|
+
function l(t) {
|
|
3
|
+
const n = parseInt(t, 16);
|
|
4
|
+
return Number.isNaN(n) ? 0 : n;
|
|
5
|
+
}
|
|
2
6
|
function a(t) {
|
|
3
|
-
|
|
7
|
+
const n = l(t) / 255;
|
|
8
|
+
return n <= 0.03928 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
|
|
4
9
|
}
|
|
5
10
|
function o(t) {
|
|
6
|
-
return
|
|
11
|
+
return 0.2126 * a(t.slice(1, 3)) + 0.7152 * a(t.slice(3, 5)) + 0.0722 * a(t.slice(-2));
|
|
7
12
|
}
|
|
8
|
-
function u(t) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function i(t, e) {
|
|
12
|
-
const n = u(t), r = u(e);
|
|
13
|
-
return (Math.max(n, r) + 0.05) / (Math.min(n, r) + 0.05);
|
|
13
|
+
function u(t, n) {
|
|
14
|
+
const e = o(t), r = o(n);
|
|
15
|
+
return (Math.max(e, r) + 0.05) / (Math.min(e, r) + 0.05);
|
|
14
16
|
}
|
|
15
17
|
function c(t) {
|
|
16
|
-
return getComputedStyle(document.documentElement).getPropertyValue(`--color-${t}`);
|
|
17
|
-
}
|
|
18
|
-
function l(t) {
|
|
19
|
-
const e = Object.values(g);
|
|
20
|
-
return e.includes(t) ? c(t) : e.find((s) => s.split("-")[0] === t) ? c(`${t}-500`) : "";
|
|
18
|
+
return getComputedStyle(document.documentElement).getPropertyValue(`--color-${t}`).trim();
|
|
21
19
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
20
|
+
function d(t) {
|
|
21
|
+
const n = Object.values(g);
|
|
22
|
+
return n.includes(t) ? c(t) : n.find((s) => s.split("-")[0] === t) ? c(`${t}-500`) : "";
|
|
24
23
|
}
|
|
25
24
|
function f(t) {
|
|
26
|
-
|
|
27
|
-
return r > s ? n : e;
|
|
25
|
+
return t.startsWith("#") ? t : `#${t}`;
|
|
28
26
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
function m(t) {
|
|
28
|
+
const n = "#27282A", e = "#FFFFFF", r = u(t, e), s = u(t, n);
|
|
29
|
+
return r > s ? e : n;
|
|
30
|
+
}
|
|
31
|
+
const i = "#27282A";
|
|
32
|
+
function p(t) {
|
|
33
|
+
if (!(t != null && t.trim()))
|
|
34
|
+
return i;
|
|
35
|
+
const n = new RegExp("^#?(([A-Fa-f0-9]{3})|([A-Fa-f0-9]{6}))$");
|
|
36
|
+
if (n.test(t)) {
|
|
37
|
+
const r = f(t);
|
|
38
|
+
return m(r);
|
|
39
|
+
}
|
|
40
|
+
if (typeof document > "u")
|
|
41
|
+
return i;
|
|
42
|
+
const e = d(t);
|
|
43
|
+
if (e && n.test(e.trim())) {
|
|
44
|
+
const r = f(e.trim());
|
|
45
|
+
return m(r);
|
|
33
46
|
}
|
|
34
|
-
|
|
35
|
-
return n ? f(n) : (console.warn(`getContrastingTextColor received an invalid color value: ${t}`), "#27282A");
|
|
47
|
+
return process.env.NODE_ENV !== "production" && console.warn(`getContrastingTextColor received an invalid color value: ${t}`), i;
|
|
36
48
|
}
|
|
37
49
|
export {
|
|
38
|
-
|
|
50
|
+
p as default
|
|
39
51
|
};
|
|
40
52
|
//# sourceMappingURL=getContrastingTextColor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getContrastingTextColor.js","sources":["../../src/utils/getContrastingTextColor.ts"],"sourcesContent":["import { StashColors } from '../../types/colors';\n\n/**\n * @see: https://wunnle.com/dynamic-text-color-based-on-background\n */\n\nfunction getRGB(c) {\n
|
|
1
|
+
{"version":3,"file":"getContrastingTextColor.js","sources":["../../src/utils/getContrastingTextColor.ts"],"sourcesContent":["import { StashColors } from '../../types/colors';\n\n/**\n * @see: https://wunnle.com/dynamic-text-color-based-on-background\n */\n\nfunction getRGB(c: string): number {\n const parsed = parseInt(c, 16);\n\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\nfunction getsRGB(c: string): number {\n const r = getRGB(c) / 255;\n\n return r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);\n}\n\nfunction getLuminance(hexColor: string): number {\n return (\n 0.2126 * getsRGB(hexColor.slice(1, 3)) +\n 0.7152 * getsRGB(hexColor.slice(3, 5)) +\n 0.0722 * getsRGB(hexColor.slice(-2))\n );\n}\n\nfunction getContrast(foreground: string, background: string): number {\n const L1 = getLuminance(foreground);\n const L2 = getLuminance(background);\n\n return (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);\n}\n\nfunction getStashColorValueFromCssVar(color: string) {\n return getComputedStyle(document.documentElement).getPropertyValue(`--color-${color}`).trim();\n}\n\nfunction getStashColor(color: string) {\n // String enum values at runtime; widen to string[] so .includes(color) is type-safe (code-patterns: avoid assertions where possible).\n const stashColors: string[] = Object.values(StashColors);\n const exactMatch = stashColors.includes(color);\n\n if (exactMatch) {\n return getStashColorValueFromCssVar(color);\n }\n\n // check if a primary color group is provided, eg. 'blue' in 'blue-100'\n const partialMatch = stashColors.find((stashColor) => {\n return stashColor.split('-')[0] === color;\n });\n\n if (partialMatch) {\n return getStashColorValueFromCssVar(`${color}-500`);\n }\n\n return '';\n}\n\nfunction normalizeHexValue(hexValue: string) {\n if (hexValue.startsWith('#')) {\n return hexValue;\n }\n\n return `#${hexValue}`;\n}\n\nfunction getContrastingHexValue(colorHexValue: string) {\n const darkTextColor = '#27282A'; // ice-900\n const lightTextColor = '#FFFFFF'; // white\n const lightTextContrast = getContrast(colorHexValue, lightTextColor);\n const darkTextContrast = getContrast(colorHexValue, darkTextColor);\n\n return lightTextContrast > darkTextContrast ? lightTextColor : darkTextColor;\n}\n\nconst DEFAULT_CONTRAST_COLOR = '#27282A';\n\n/**\n * Returns a contrasting text color (light or dark) for a given background color.\n * Accepts hex values or Stash color names (resolved via CSS variables in the browser).\n * In SSR or when the color is invalid, returns the default contrast color (ice-900).\n *\n * @param color - Hex string (e.g. #fff or abc123) or Stash color name (e.g. blue-500)\n * @returns Hex string for the contrasting text color\n */\nexport default function getContrastingTextColor(color: string) {\n if (!color?.trim()) {\n return DEFAULT_CONTRAST_COLOR;\n }\n\n const hexRegex = new RegExp('^#?(([A-Fa-f0-9]{3})|([A-Fa-f0-9]{6}))$');\n\n if (hexRegex.test(color)) {\n const normalizedHexValue = normalizeHexValue(color);\n return getContrastingHexValue(normalizedHexValue);\n }\n\n // Stash color names require getComputedStyle(document.documentElement), which is unavailable in SSR (Node).\n if (typeof document === 'undefined') {\n return DEFAULT_CONTRAST_COLOR;\n }\n\n const stashColor = getStashColor(color);\n\n if (stashColor && hexRegex.test(stashColor.trim())) {\n const normalized = normalizeHexValue(stashColor.trim());\n return getContrastingHexValue(normalized);\n }\n\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`getContrastingTextColor received an invalid color value: ${color}`);\n }\n\n return DEFAULT_CONTRAST_COLOR;\n}\n"],"names":["getRGB","c","parsed","getsRGB","r","getLuminance","hexColor","getContrast","foreground","background","L1","L2","getStashColorValueFromCssVar","color","getStashColor","stashColors","StashColors","stashColor","normalizeHexValue","hexValue","getContrastingHexValue","colorHexValue","darkTextColor","lightTextColor","lightTextContrast","darkTextContrast","DEFAULT_CONTRAST_COLOR","getContrastingTextColor","hexRegex","normalizedHexValue","normalized"],"mappings":";AAMA,SAASA,EAAOC,GAAmB;AACjC,QAAMC,IAAS,SAASD,GAAG,EAAE;AAE7B,SAAO,OAAO,MAAMC,CAAM,IAAI,IAAIA;AACpC;AAEA,SAASC,EAAQF,GAAmB;AAClC,QAAMG,IAAIJ,EAAOC,CAAC,IAAI;AAEtB,SAAOG,KAAK,UAAUA,IAAI,QAAQ,KAAK,KAAKA,IAAI,SAAS,OAAO,GAAG;AACrE;AAEA,SAASC,EAAaC,GAA0B;AAC9C,SACE,SAASH,EAAQG,EAAS,MAAM,GAAG,CAAC,CAAC,IACrC,SAASH,EAAQG,EAAS,MAAM,GAAG,CAAC,CAAC,IACrC,SAASH,EAAQG,EAAS,MAAM,EAAE,CAAC;AAEvC;AAEA,SAASC,EAAYC,GAAoBC,GAA4B;AACnE,QAAMC,IAAKL,EAAaG,CAAU,GAC5BG,IAAKN,EAAaI,CAAU;AAElC,UAAQ,KAAK,IAAIC,GAAIC,CAAE,IAAI,SAAS,KAAK,IAAID,GAAIC,CAAE,IAAI;AACzD;AAEA,SAASC,EAA6BC,GAAe;AACnD,SAAO,iBAAiB,SAAS,eAAe,EAAE,iBAAiB,WAAWA,CAAK,EAAE,EAAE,KAAA;AACzF;AAEA,SAASC,EAAcD,GAAe;AAEpC,QAAME,IAAwB,OAAO,OAAOC,CAAW;AAGvD,SAFmBD,EAAY,SAASF,CAAK,IAGpCD,EAA6BC,CAAK,IAItBE,EAAY,KAAK,CAACE,MAC9BA,EAAW,MAAM,GAAG,EAAE,CAAC,MAAMJ,CACrC,IAGQD,EAA6B,GAAGC,CAAK,MAAM,IAG7C;AACT;AAEA,SAASK,EAAkBC,GAAkB;AAC3C,SAAIA,EAAS,WAAW,GAAG,IAClBA,IAGF,IAAIA,CAAQ;AACrB;AAEA,SAASC,EAAuBC,GAAuB;AACrD,QAAMC,IAAgB,WAChBC,IAAiB,WACjBC,IAAoBjB,EAAYc,GAAeE,CAAc,GAC7DE,IAAmBlB,EAAYc,GAAeC,CAAa;AAEjE,SAAOE,IAAoBC,IAAmBF,IAAiBD;AACjE;AAEA,MAAMI,IAAyB;AAU/B,SAAwBC,EAAwBd,GAAe;AAC7D,MAAI,EAACA,KAAA,QAAAA,EAAO;AACV,WAAOa;AAGT,QAAME,IAAW,IAAI,OAAO,yCAAyC;AAErE,MAAIA,EAAS,KAAKf,CAAK,GAAG;AACxB,UAAMgB,IAAqBX,EAAkBL,CAAK;AAClD,WAAOO,EAAuBS,CAAkB;AAAA,EAClD;AAGA,MAAI,OAAO,WAAa;AACtB,WAAOH;AAGT,QAAMT,IAAaH,EAAcD,CAAK;AAEtC,MAAII,KAAcW,EAAS,KAAKX,EAAW,KAAA,CAAM,GAAG;AAClD,UAAMa,IAAaZ,EAAkBD,EAAW,KAAA,CAAM;AACtD,WAAOG,EAAuBU,CAAU;AAAA,EAC1C;AAEA,SAAI,QAAQ,IAAI,aAAa,gBAE3B,QAAQ,KAAK,4DAA4DjB,CAAK,EAAE,GAG3Ea;AACT;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leaflink/stash",
|
|
3
|
-
"version": "53.4.
|
|
3
|
+
"version": "53.4.8",
|
|
4
4
|
"description": "LeafLink's design system.",
|
|
5
5
|
"homepage": "https://stash.leaflink.com",
|
|
6
6
|
"main": "./dist/index.ts",
|
|
@@ -86,7 +86,6 @@
|
|
|
86
86
|
"date-fns": "3.6.0",
|
|
87
87
|
"date-fns-tz": "3.1.3",
|
|
88
88
|
"dompurify": "3.2.4",
|
|
89
|
-
"flat": "6.0.1",
|
|
90
89
|
"fuzzysort": "3.0.2",
|
|
91
90
|
"sanitize-html": "2.13.0",
|
|
92
91
|
"v-calendar": "3.1.2",
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { defineComponent as L, computed as f, provide as N, useTemplateRef as x, onMounted as R, onUpdated as S, watch as B, onBeforeUnmount as $, createElementBlock as y, openBlock as v, createBlock as D, unref as C, normalizeClass as b, withCtx as p, renderSlot as h, createElementVNode as A, createTextVNode as H, createVNode as O, toDisplayString as j } from "vue";
|
|
2
|
-
import { t as E } from "./locale.js";
|
|
3
|
-
import q from "./Icon.js";
|
|
4
|
-
import z from "./MoreActions.js";
|
|
5
|
-
const J = Object.freeze({
|
|
6
|
-
key: Symbol("TABS_INJECTION_KEY")
|
|
7
|
-
});
|
|
8
|
-
var g = /* @__PURE__ */ ((e) => (e.Line = "line", e.Enclosed = "enclosed", e))(g || {});
|
|
9
|
-
const U = ["aria-expanded", "onClick"], G = /* @__PURE__ */ L({
|
|
10
|
-
__name: "Tabs",
|
|
11
|
-
props: {
|
|
12
|
-
activeTab: {},
|
|
13
|
-
variant: { default: g.Line }
|
|
14
|
-
},
|
|
15
|
-
emits: ["update:activeTab"],
|
|
16
|
-
setup(e, { emit: w }) {
|
|
17
|
-
const M = w, o = e, s = f({
|
|
18
|
-
get() {
|
|
19
|
-
return o.activeTab;
|
|
20
|
-
},
|
|
21
|
-
set(t) {
|
|
22
|
-
M("update:activeTab", t);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
function I(t) {
|
|
26
|
-
s.value = t;
|
|
27
|
-
}
|
|
28
|
-
N(J.key, {
|
|
29
|
-
activeTab: f(() => s.value),
|
|
30
|
-
variant: f(() => o.variant),
|
|
31
|
-
setActiveTab: I
|
|
32
|
-
});
|
|
33
|
-
const r = x("moreDropdownMenuRef"), i = x("tabsContainerRef"), c = /* @__PURE__ */ new Map();
|
|
34
|
-
function k() {
|
|
35
|
-
c.forEach((t, a) => {
|
|
36
|
-
a.removeEventListener("click", t);
|
|
37
|
-
}), c.clear();
|
|
38
|
-
}
|
|
39
|
-
function l() {
|
|
40
|
-
if (!r.value) return;
|
|
41
|
-
k(), r.value.querySelectorAll("[data-action-id]").forEach((a) => {
|
|
42
|
-
const n = a.getAttribute("data-action-id");
|
|
43
|
-
if (!n) return;
|
|
44
|
-
const d = s.value === n;
|
|
45
|
-
a.setAttribute("aria-selected", d ? "true" : "false");
|
|
46
|
-
const T = () => {
|
|
47
|
-
if (i.value) {
|
|
48
|
-
const u = i.value.querySelector(
|
|
49
|
-
`[role="tab"][data-action-id="${n}"]`
|
|
50
|
-
), m = u == null ? void 0 : u.firstChild;
|
|
51
|
-
m && m instanceof HTMLElement && m.click();
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
a.addEventListener("click", T), c.set(a, T);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
return R(() => {
|
|
58
|
-
l();
|
|
59
|
-
}), S(() => {
|
|
60
|
-
l();
|
|
61
|
-
}), B(s, () => {
|
|
62
|
-
l();
|
|
63
|
-
}), $(() => {
|
|
64
|
-
k();
|
|
65
|
-
}), (t, a) => (v(), y("div", {
|
|
66
|
-
ref_key: "tabsContainerRef",
|
|
67
|
-
ref: i,
|
|
68
|
-
class: "stash-tabs relative",
|
|
69
|
-
role: "tabList",
|
|
70
|
-
"data-test": "stash-tabs"
|
|
71
|
-
}, [
|
|
72
|
-
t.$slots["more-actions"] ? (v(), D(z, {
|
|
73
|
-
key: 0,
|
|
74
|
-
class: b(["stash-tabs-list flex items-end", {
|
|
75
|
-
"stash-tabs-list--line": e.variant === "line",
|
|
76
|
-
"stash-tabs-list--enclosed": e.variant === "enclosed",
|
|
77
|
-
"gap-6": e.variant === "line"
|
|
78
|
-
}]),
|
|
79
|
-
"more-button-text": C(E)("ll.more"),
|
|
80
|
-
"dropdown-mode": "custom",
|
|
81
|
-
"actions-container-class": {
|
|
82
|
-
"gap-0": e.variant === "enclosed",
|
|
83
|
-
"gap-6": e.variant === "line"
|
|
84
|
-
},
|
|
85
|
-
"actions-container-tag": "ul"
|
|
86
|
-
}, {
|
|
87
|
-
"more-actions": p(() => [
|
|
88
|
-
A("div", {
|
|
89
|
-
ref_key: "moreDropdownMenuRef",
|
|
90
|
-
ref: r
|
|
91
|
-
}, [
|
|
92
|
-
h(t.$slots, "more-actions")
|
|
93
|
-
], 512)
|
|
94
|
-
]),
|
|
95
|
-
toggle: p(({ toggle: n, isOpen: d }) => [
|
|
96
|
-
A("button", {
|
|
97
|
-
"aria-haspopup": "menu",
|
|
98
|
-
"aria-expanded": d,
|
|
99
|
-
class: b(["flex cursor-pointer items-center justify-center border-solid px-6 pt-1.5 pb-1 text-sm font-medium text-blue-500 hover:text-blue-700", { "border-t-4 border-transparent": o.variant === "enclosed" }]),
|
|
100
|
-
type: "button",
|
|
101
|
-
onClick: n
|
|
102
|
-
}, [
|
|
103
|
-
H(j(C(E)("ll.more")) + " ", 1),
|
|
104
|
-
O(q, { name: "caret-down" })
|
|
105
|
-
], 10, U)
|
|
106
|
-
]),
|
|
107
|
-
default: p(() => [
|
|
108
|
-
h(t.$slots, "default")
|
|
109
|
-
]),
|
|
110
|
-
_: 3
|
|
111
|
-
}, 8, ["class", "more-button-text", "actions-container-class"])) : (v(), y("ul", {
|
|
112
|
-
key: 1,
|
|
113
|
-
class: b(["stash-tabs-list flex items-end overflow-x-scroll", {
|
|
114
|
-
"stash-tabs-list--line": e.variant === "line",
|
|
115
|
-
"stash-tabs-list--enclosed": e.variant === "enclosed",
|
|
116
|
-
"gap-0": e.variant === "enclosed",
|
|
117
|
-
"gap-6": e.variant === "line"
|
|
118
|
-
}])
|
|
119
|
-
}, [
|
|
120
|
-
h(t.$slots, "default")
|
|
121
|
-
], 2))
|
|
122
|
-
], 512));
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
export {
|
|
126
|
-
J as T,
|
|
127
|
-
G as _,
|
|
128
|
-
g as a
|
|
129
|
-
};
|
|
130
|
-
//# sourceMappingURL=Tabs.vue_vue_type_script_setup_true_lang-B3FBaVP5.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.vue_vue_type_script_setup_true_lang-B3FBaVP5.js","sources":["../src/components/Tabs/keys.ts","../src/components/Tabs/models.ts","../src/components/Tabs/Tabs.vue"],"sourcesContent":["import { Injection } from '../../../types/utils';\nimport { TabsInjection } from './models';\n\nexport const TABS_INJECTION: Injection<TabsInjection> = Object.freeze({\n key: Symbol('TABS_INJECTION_KEY'),\n});\n","import { ComputedRef } from 'vue';\n\nexport enum TabVariant {\n Line = 'line',\n Enclosed = 'enclosed',\n}\n\nexport type TabVariants = `${TabVariant}`;\n\nexport interface TabsInjection {\n activeTab: ComputedRef<string>;\n variant: ComputedRef<TabVariants>;\n setActiveTab: (newTabValue: string) => void;\n}\n","<script lang=\"ts\">\n import { TabVariant, TabVariants } from './models';\n\n export * from './keys';\n export * from './models';\n\n export interface TabsProps {\n /**\n * The currently active tab value\n */\n activeTab: string;\n\n /**\n * Tabs variant\n */\n variant?: TabVariants;\n }\n</script>\n\n<script setup lang=\"ts\">\n import { computed, onBeforeUnmount, onMounted, onUpdated, provide, useTemplateRef, watch } from 'vue';\n\n import { t } from '../../locale';\n import Icon from '../Icon/Icon.vue';\n import MoreActions from '../MoreActions/MoreActions.vue';\n import { TABS_INJECTION } from './keys';\n\n const emit = defineEmits<{\n (e: 'update:activeTab', newTabValue: TabsProps['activeTab']): void;\n }>();\n\n const props = withDefaults(defineProps<TabsProps>(), {\n variant: TabVariant.Line,\n });\n\n const currentActiveTab = computed({\n get() {\n return props.activeTab;\n },\n set(nv: TabsProps['activeTab']) {\n emit('update:activeTab', nv);\n },\n });\n\n function setActiveTab(newTabValue: TabsProps['activeTab']) {\n currentActiveTab.value = newTabValue;\n }\n\n provide(TABS_INJECTION.key, {\n activeTab: computed(() => currentActiveTab.value),\n variant: computed(() => props.variant),\n setActiveTab,\n });\n\n const moreDropdownMenuRef = useTemplateRef<HTMLElement>('moreDropdownMenuRef');\n const tabsContainerRef = useTemplateRef<HTMLElement>('tabsContainerRef');\n\n // Store event listeners to allow proper cleanup\n const eventListeners = new Map<Element, EventListener>();\n\n function cleanupMoreActionsHandlers() {\n eventListeners.forEach((listener, element) => {\n element.removeEventListener('click', listener);\n });\n eventListeners.clear();\n }\n\n // Setup automatic handlers for MenuItem elements in more-actions dropdown\n function setupMoreActionsHandlers() {\n if (!moreDropdownMenuRef.value) return;\n\n // Remove existing listeners first to prevent duplication\n cleanupMoreActionsHandlers();\n\n const menuItems = moreDropdownMenuRef.value.querySelectorAll('[data-action-id]');\n\n menuItems.forEach((item) => {\n const actionId = item.getAttribute('data-action-id');\n if (!actionId) return;\n\n // Update aria-selected based on active tab\n const isActive = currentActiveTab.value === actionId;\n item.setAttribute('aria-selected', isActive ? 'true' : 'false');\n\n // Create and store the listener\n const listener = () => {\n // Find and click the original tab in the actions container\n if (tabsContainerRef.value) {\n const originalTab = tabsContainerRef.value.querySelector<HTMLElement>(\n `[role=\"tab\"][data-action-id=\"${actionId}\"]`,\n );\n const firstChild = originalTab?.firstChild;\n if (firstChild && firstChild instanceof HTMLElement) {\n firstChild.click();\n }\n }\n };\n\n item.addEventListener('click', listener);\n eventListeners.set(item, listener);\n });\n }\n\n onMounted(() => {\n setupMoreActionsHandlers();\n });\n\n onUpdated(() => {\n setupMoreActionsHandlers();\n });\n\n watch(currentActiveTab, () => {\n setupMoreActionsHandlers();\n });\n\n onBeforeUnmount(() => {\n cleanupMoreActionsHandlers();\n });\n</script>\n\n<template>\n <div ref=\"tabsContainerRef\" class=\"stash-tabs relative\" role=\"tabList\" data-test=\"stash-tabs\">\n <template v-if=\"$slots['more-actions']\">\n <MoreActions\n class=\"stash-tabs-list flex items-end\"\n :class=\"{\n 'stash-tabs-list--line': variant === 'line',\n 'stash-tabs-list--enclosed': variant === 'enclosed',\n 'gap-6': variant === 'line',\n }\"\n :more-button-text=\"t('ll.more')\"\n dropdown-mode=\"custom\"\n :actions-container-class=\"{\n 'gap-0': variant === 'enclosed',\n 'gap-6': variant === 'line',\n }\"\n actions-container-tag=\"ul\"\n >\n <slot></slot>\n\n <template #more-actions>\n <div ref=\"moreDropdownMenuRef\">\n <slot name=\"more-actions\"></slot>\n </div>\n </template>\n\n <template #toggle=\"{ toggle, isOpen }\">\n <button\n aria-haspopup=\"menu\"\n :aria-expanded=\"isOpen\"\n class=\"flex cursor-pointer items-center justify-center border-solid px-6 pt-1.5 pb-1 text-sm font-medium text-blue-500 hover:text-blue-700\"\n :class=\"{ 'border-t-4 border-transparent': props.variant === 'enclosed' }\"\n type=\"button\"\n @click=\"toggle\"\n >\n {{ t('ll.more') }}\n <Icon name=\"caret-down\" />\n </button>\n </template>\n </MoreActions>\n </template>\n\n <template v-else>\n <ul\n class=\"stash-tabs-list flex items-end overflow-x-scroll\"\n :class=\"{\n 'stash-tabs-list--line': variant === 'line',\n 'stash-tabs-list--enclosed': variant === 'enclosed',\n 'gap-0': variant === 'enclosed',\n 'gap-6': variant === 'line',\n }\"\n >\n <slot></slot>\n </ul>\n </template>\n </div>\n</template>\n"],"names":["TABS_INJECTION","TabVariant","emit","__emit","props","__props","currentActiveTab","computed","nv","setActiveTab","newTabValue","provide","moreDropdownMenuRef","useTemplateRef","tabsContainerRef","eventListeners","cleanupMoreActionsHandlers","listener","element","setupMoreActionsHandlers","item","actionId","isActive","originalTab","firstChild","onMounted","onUpdated","watch","onBeforeUnmount","_createElementBlock","$slots","_createBlock","MoreActions","_unref","t","_createElementVNode","_renderSlot","_ctx","_withCtx","toggle","isOpen","_normalizeClass","_createTextVNode","_toDisplayString","_createVNode","Icon"],"mappings":"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"}
|