{"version":3,"file":"codeBox.obs.js","sources":["../../src/Security/codeBox.obs","../../../Rock.JavaScript.Obsidian/node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["<!-- Copyright by the Spark Development Network; Licensed under the Rock Community License -->\r\n<template>\r\n    <RockFormField\r\n        v-model=\"internalModelValue\"\r\n        name=\"codebox\"\r\n        :rules=\"rules\">\r\n        <template #default=\"{uniqueId, field}\">\r\n            <div :class=\"['form-group rock-code-box', isRequired ? 'required' : '']\">\r\n                <div class=\"control-wrapper\">\r\n                    <div class=\"d-flex\" ref=\"codeContainer\">\r\n                        <input\r\n                            v-for=\"(character, index) in characters\"\r\n                            v-model=\"characters[index]\"\r\n                            autocomplete=\"one-time-code\"\r\n                            :autofocus=\"index === 0\"\r\n                            :class=\"`form-control flex-grow-1 flex-sm-grow-0 flex-shrink-1 ${index > 0 ? 'ml-1' : ''} h3`\"\r\n                            :disabled=\"disabled\"\r\n                            :id=\"`${uniqueId}-${index}`\"\r\n                            :key=\"index\"\r\n                            :maxlength=\"maxLength\"\r\n                            type=\"text\"\r\n                            @input=\"onInput($event, index)\"\r\n                            @focus=\"onFocus(index)\" />\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </template>\r\n    </RockFormField>\r\n</template>\r\n\r\n<style scoped>\r\n.rock-code-box input {\r\n    width: 47px;\r\n    height: 64px;\r\n    text-align: center;\r\n    font-size: 24px;\r\n}\r\n</style>\r\n\r\n<script setup lang=\"ts\">\r\n    import RockFormField from \"@Obsidian/Controls/rockFormField\";\r\n    import { useVModelPassthrough } from \"@Obsidian/Utility/component\";\r\n    import { normalizeRules, rulesPropType } from \"@Obsidian/ValidationRules\";\r\n    import { computed, nextTick, ref, reactive, PropType, VNodeRef, watch } from \"vue\";\r\n\r\n    type CodeBoxModelModifiers = {\r\n        capitalize?: unknown\r\n    };\r\n\r\n    const props = defineProps({\r\n        modelValue: {\r\n            type: String as PropType<string>,\r\n            required: false,\r\n            default: null\r\n        },\r\n\r\n        allowedChars: {\r\n            type: Object as PropType<RegExp>,\r\n            required: false,\r\n            default: /^[a-zA-Z0-9]$/\r\n        },\r\n\r\n        disabled: {\r\n            type: Boolean as PropType<boolean>,\r\n            required: false,\r\n            default: false\r\n        },\r\n\r\n        maxLength: {\r\n            type: Number as PropType<number>,\r\n            required: true\r\n        },\r\n\r\n        modelModifiers: {\r\n            type: Object as PropType<CodeBoxModelModifiers>,\r\n            required: false,\r\n            default: null\r\n        },\r\n\r\n        rules: rulesPropType,\r\n\r\n        updateOnComplete: {\r\n            type: Boolean as PropType<boolean>,\r\n            required: false,\r\n            default: false\r\n        }\r\n    });\r\n\r\n    const emit = defineEmits<{\r\n        (e: \"update:modelValue\", value: string): void,\r\n        (e: \"complete\", value: string): void\r\n    }>();\r\n\r\n    //#region Values\r\n\r\n    const internalModelValue = useVModelPassthrough(props, \"modelValue\", emit);\r\n\r\n    const codeContainer = ref<VNodeRef | undefined>(undefined);\r\n\r\n    const characters = reactive<(string | null | undefined)[]>([]);\r\n\r\n    setCharactersFromModelValue();\r\n\r\n    //#endregion\r\n\r\n    //#region Computed Values\r\n\r\n    /** The internal rules we will be used for calculations. */\r\n    const internalRules = computed(() => normalizeRules(props.rules));\r\n\r\n    /** Determines if this field is marked as required. */\r\n    const isRequired = computed(() => internalRules.value.includes(\"required\"));\r\n\r\n    //#endregion\r\n\r\n    //#region Event Handlers\r\n\r\n    /**\r\n     * Event handler for an input receiving input.\r\n     *\r\n     * @param event The input event.\r\n     * @param index The code character input index.\r\n     */\r\n    function onInput(event: Event, index: number): void {\r\n        if (!isInputEvent(event)) {\r\n            return;\r\n        }\r\n\r\n        const input = getCodeInputAt(index);\r\n\r\n        if (!input || input !== event.target) {\r\n            return;\r\n        }\r\n\r\n        const modifiedString = applyModifications(input.value);\r\n        const modifiedCharacters = modifiedString.split(\"\");\r\n\r\n        let lastFilledIndex = -1;\r\n        for (let i = 0; i < modifiedCharacters.length; i++) {\r\n            if (index + i < props.maxLength) {\r\n                lastFilledIndex = index + i;\r\n                characters[lastFilledIndex] = modifiedCharacters[i];\r\n            }\r\n        }\r\n\r\n        // Emit first, then focus on the next tick.\r\n        tryEmitCode();\r\n\r\n        nextTick(() => {\r\n            if (lastFilledIndex !== -1) {\r\n                // Focus on the next input.\r\n                const nextInput = lastFilledIndex < props.maxLength - 2 ? getCodeInputAt(lastFilledIndex + 1) : getCodeInputAt(lastFilledIndex);\r\n                if (nextInput) {\r\n                    nextInput.focus();\r\n                }\r\n            }\r\n            else if (event.inputType === \"deleteContentBackward\") {\r\n                // Focus on the previous input.\r\n                const prevInput = index === 0 ? getCodeInputAt(index) : getCodeInputAt(index - 1);\r\n                if (prevInput) {\r\n                    prevInput.focus();\r\n                }\r\n            }\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Event handler for an input being focused.\r\n     *\r\n     * @param index The input index.\r\n     */\r\n    function onFocus(index: number): void {\r\n        const input = getCodeInputAt(index);\r\n\r\n        if (input) {\r\n            input.select();\r\n        }\r\n    }\r\n\r\n    //#endregion\r\n\r\n    //#region Functions\r\n\r\n    /**\r\n     * Applies model modifications to a single code character.\r\n     *\r\n     * @param codeCharacter The code character to which to apply modifications.\r\n     */\r\n    function applyModifications(codeCharacter: string): string {\r\n        if (codeCharacter && props.modelModifiers?.capitalize) {\r\n            return codeCharacter.toUpperCase();\r\n        }\r\n\r\n        return codeCharacter;\r\n    }\r\n\r\n    /**\r\n     * Gets the code character input element at a given index.\r\n     *\r\n     * @param index The code character input index.\r\n     */\r\n    function getCodeInputAt(index: number): HTMLInputElement {\r\n        return (codeContainer.value.children)[index];\r\n    }\r\n\r\n    /**\r\n     * Determines whether every character in the code is complete.\r\n     */\r\n    function isCodeComplete(): boolean {\r\n        for (const character of characters) {\r\n            if (character == null || character == undefined) {\r\n                return false;\r\n            }\r\n        }\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * Determines whether the event is an InputEvent.\r\n     *\r\n     * @param event The event to check.\r\n     */\r\n    function isInputEvent(event: unknown): event is InputEvent {\r\n        return !!event && typeof event === \"object\" && \"inputType\" in event;\r\n    }\r\n\r\n    /**\r\n     * Sets characters from props.modelValue if different than current value.\r\n     *\r\n     * If applying modifications to props.modelValue results in a different value,\r\n     * then this method will emit the new value.\r\n     */\r\n    function setCharactersFromModelValue(): void {\r\n        if (!characters.length || props.modelValue != characters.join(\"\")) {\r\n            if (props.modelValue) {\r\n                for (let index = 0; index < props.maxLength; index++) {\r\n                    characters[index] = applyModifications(props.modelValue.charAt(index));\r\n                }\r\n\r\n                const newModelValue = characters.join(\"\");\r\n                if (props.modelValue != newModelValue) {\r\n                    nextTick(() => {\r\n                        tryEmitCode();\r\n                    });\r\n                }\r\n            }\r\n            else {\r\n                for (let index = 0; index < props.maxLength; index++) {\r\n                    characters[index] = null;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Tries to emit \"update:modelValue\" and \"complete\" events if code is valid.\r\n     */\r\n    function tryEmitCode(): boolean {\r\n        const isComplete = isCodeComplete();\r\n        if (!props.updateOnComplete || isComplete) {\r\n            const code = characters.join(\"\");\r\n            emit(\"update:modelValue\", code);\r\n\r\n            if (isComplete) {\r\n                emit(\"complete\", code);\r\n            }\r\n\r\n            return true;\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    //#endregion\r\n\r\n    //#region Watchers\r\n\r\n    watch(() => props.modelValue, () => {\r\n        setCharactersFromModelValue();\r\n    });\r\n\r\n    //#endregion\r\n</script>\r\n","function styleInject(css, ref) {\n  if ( ref === void 0 ) ref = {};\n  var insertAt = ref.insertAt;\n\n  if (!css || typeof document === 'undefined') { return; }\n\n  var head = document.head || document.getElementsByTagName('head')[0];\n  var style = document.createElement('style');\n  style.type = 'text/css';\n\n  if (insertAt === 'top') {\n    if (head.firstChild) {\n      head.insertBefore(style, head.firstChild);\n    } else {\n      head.appendChild(style);\n    }\n  } else {\n    head.appendChild(style);\n  }\n\n  if (style.styleSheet) {\n    style.styleSheet.cssText = css;\n  } else {\n    style.appendChild(document.createTextNode(css));\n  }\n}\n\nexport default styleInject;\n"],"names":["internalModelValue","useVModelPassthrough","props","emit","codeContainer","ref","undefined","characters","reactive","setCharactersFromModelValue","internalRules","computed","normalizeRules","rules","isRequired","value","includes","onInput","event","index","isInputEvent","input","getCodeInputAt","target","modifiedString","applyModifications","modifiedCharacters","split","lastFilledIndex","i","length","maxLength","tryEmitCode","nextTick","nextInput","focus","inputType","prevInput","onFocus","select","codeCharacter","_props$modelModifiers","modelModifiers","capitalize","toUpperCase","children","isCodeComplete","_iterator","_createForOfIteratorHelper","_step","s","n","done","character","err","e","f","modelValue","join","charAt","newModelValue","isComplete","updateOnComplete","code","watch","styleInject","css","insertAt","document","head","getElementsByTagName","style","createElement","type","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode"],"mappings":"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"}