diff --git a/.idea/filament-maskinput.iml b/.idea/filament-maskinput.iml index b653b19..affd345 100644 --- a/.idea/filament-maskinput.iml +++ b/.idea/filament-maskinput.iml @@ -4,6 +4,7 @@ + diff --git a/README.md b/README.md index 63a4085..20abd2f 100644 --- a/README.md +++ b/README.md @@ -51,12 +51,10 @@ php artisan vendor:publish --tag="config" - **money** - **Description**: Configures the input field for monetary values. - **Parameters**: - - `$precision` (int|null): Decimal precision. - - `$separator` (string|null): Decimal separator. - - `$delimiter` (string|null): Thousands delimiter. - - `$unit` (string|null): Currency unit prefix. - - `$suffixUnit` (string|null): Currency unit suffix. - - `$zeroCents` (bool|null): Enables or disables zero cents. + - `$decimalPrecision` (int|null): Decimal precision. + - `$decimalSeparator` (string|null): Decimal separator. + - `$thousandsSeparator` (string|null): Thousands delimiter. + - `$allowNegative` (bool|null): Allow negative. - **mask** - **Description**: Sets the mask pattern for the input. @@ -74,6 +72,12 @@ php artisan vendor:publish --tag="config" ```php MaskInput::make('money') ->money(); + +MaskInput::make('money') +->money(decimalPrecision: 3, allowNegative: true); + +output: 1.234,56 + ``` #### Dynamic Input @@ -82,6 +86,8 @@ MaskInput::make('dynamic') ->mask(RawJs::make("['999.999.999-99', '99.999.999/9999-99']")) ->stripCharacters(['.','-', '/']) ->maxLength(14) // Acts as a trigger for mask switching + +output: 123.456.789-01 or 12.345.678/9012-34 ``` #### Pattern Input @@ -89,6 +95,24 @@ MaskInput::make('dynamic') MaskInput::make('pattern') ->mask('99999-999') ->stripCharacters(['-']) + +output: 12345-678 +``` + +```php +MaskInput::make('pattern') +->mask('SS.SS.SSSSS.S.S.SSSSSS') +->stripCharacters(['.']) + +output: 9B.GR.D08X0.4.G.117974 +``` + +```php +MaskInput::make('pattern') +->mask('AAA-9999') +->stripCharacters(['-']) + +output: ABC-1234 ``` ## Testing diff --git a/config/filament-maskinput.php b/config/filament-maskinput.php index 0c02b52..10638dc 100644 --- a/config/filament-maskinput.php +++ b/config/filament-maskinput.php @@ -1,10 +1,8 @@ 2, - 'separator' => ',', - 'delimiter' => '.', - 'unit' => 'R$', - 'suffixUnit' => null, - 'zeroCents' => false, + 'allowNegative' => false, + 'decimalPrecision' => 2, + 'thousandsSeparator' => '.', + 'decimalSeparator' => ',', ]; diff --git a/dist/filament-maskinput.js b/dist/filament-maskinput.js index 87160f0..3090889 100644 --- a/dist/filament-maskinput.js +++ b/dist/filament-maskinput.js @@ -1 +1 @@ -(()=>{var x=Object.create;var O=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var I=(r,n)=>()=>(n||r((n={exports:{}}).exports,n),n.exports);var L=(r,n,m,v)=>{if(n&&typeof n=="object"||typeof n=="function")for(let d of V(n))!H.call(r,d)&&d!==m&&O(r,d,{get:()=>n[d],enumerable:!(v=R(n,d))||v.enumerable});return r};var $=(r,n,m)=>(m=r!=null?x(W(r)):{},L(n||!r||!r.__esModule?O(m,"default",{value:r,enumerable:!0}):m,r));var j=I((E,T)=>{(function(r,n){typeof define=="function"&&define.amd?define(n):typeof E=="object"?T.exports=n():r.VMasker=n()})(E,function(){var r="9",n="A",m="S",v=[9,16,17,18,36,37,38,39,40,91,92,93],d=function(e){for(var t=0,o=v.length;tA?t.precision:A;w=(w+P).slice(-N)}var U=t.unit+S+u+t.separator+w;return U.replace(l,"")+t.suffixUnit},g.toPattern=function(e,t){var o=typeof t=="object"?t.pattern:t,h=o.replace(/\W/g,""),i=o.split(""),s=e.toString().replace(/\W/g,""),a=s.replace(/\W/g,""),k=0,l,p=i.length,u=typeof t=="object"?t.placeholder:void 0;for(l=0;l=s.length){if(h.length==a.length)return i.join("");if(u!==void 0&&h.length>a.length)return c(i,l,u).join("");break}else if(i[l]===r&&s[k].match(/[0-9]/)||i[l]===n&&s[k].match(/[a-zA-Z]/)||i[l]===m&&s[k].match(/[0-9a-zA-Z]/))i[l]=s[k++];else if(i[l]===r||i[l]===n||i[l]===m)return u!==void 0?c(i,l,u).join(""):i.slice(0,l).join("");return i.join("").substr(0,l)},g.toNumber=function(e){return e.toString().replace(/(?!^-)[^0-9]/g,"")},g.toAlphaNumeric=function(e){return e.toString().replace(/[^a-z0-9 ]+/i,"")},g})});var y=$(j(),1),z=r=>{let n=document.getElementById(r);if(!n)return console.warn(`Elemento inv\xE1lido com id: ${r}`),null;let m=(c,f,g)=>{let e=g.target,t=e.value.replace(/\D/g,""),o=e.value.length>f?1:0;(0,y.default)(e).unMask(),(0,y.default)(e).maskPattern(c[o]),e.value=y.default.toPattern(t,c[o])};return{dynamicMask:(c,f=1)=>{(0,y.default)(n).maskPattern(c[0]),n.addEventListener("input",g=>m(c,f,g),!1)},maskPattern:c=>{(0,y.default)(n).maskPattern(`${c}`)},maskMoney:c=>{(0,y.default)(n).maskMoney(c)}}};window.FilamentMaskInput=z;})(); +(()=>{var d=(()=>{let p="9",c="A",f="S",y=[9,16,17,18,36,37,38,39,40,91,92,93],S=function(e){for(let t=0,a=y.length;tt.decimalPrecision&&(m=m.substring(0,t.decimalPrecision)),a=g+t.decimalSeparator+m,a}let r="";t.allowNegative===!0&&(r="(^[^-]?)|"),a=a.replace(new RegExp(r+`([^0-9\\${t.thousandsSeparator}\\${t.decimalSeparator}])`,"g"),""),a=a.replace(new RegExp(`\\${t.thousandsSeparator}`,"g"),"").replace(new RegExp(`\\${t.decimalSeparator}`,"g"),t.thousandsSeparator);let[n,u]=a.split(t.thousandsSeparator);return n=n.replace(/\B(?=(\d{3})+(?!\d))/g,t.thousandsSeparator),a=n+(u?t.decimalSeparator+u:""),a},s.toPattern=function(e,t){let a=typeof t=="object"?t.pattern:t,r=a.replace(/\W/g,""),n=a.split(""),u=e.toString().replace(/\W/g,""),g=u.replace(/\W/g,""),m=n.length,k=typeof t=="object"?t.placeholder:void 0,h=0,l;for(l=0;l=u.length){if(r.length===g.length)return n.join("");if(k!==void 0&&r.length>g.length)return i(n,l,k).join("");break}else if(n[l]===p&&u[h].match(/[0-9]/)||n[l]===c&&u[h].match(/[a-zA-Z]/)||n[l]===f&&u[h].match(/[0-9a-zA-Z]/))n[l]=u[h++];else{if(n[l]===p||n[l]===c||n[l]===f)return k!==void 0?i(n,l,k).join(""):n.slice(0,l).join("");n[l]===u[h]&&h++}return n.join("").slice(0,l)},s.toNumber=function(e){return e.toString().replace(/(?!^-)[^0-9]/g,"")},s.toAlphaNumeric=function(e){return e.toString().replace(/[^a-z0-9 ]+/i,"")},s})();var P=p=>{let c=document.getElementById(p);if(!c)return console.warn(`Elemento inv\xE1lido com id: ${p}`),null;let f=(i,o,s)=>{let e=s.target,t=e.value.replace(/\D/g,""),a=e.value.length>o?1:0;d(e).unMask(),d(e).maskPattern(i[a]),e.value=d.toPattern(t,i[a])};return{dynamicMask:(i,o=1)=>{d(c).maskPattern(i[0]),c.addEventListener("input",s=>f(i,o,s),!1)},maskPattern:i=>{d(c).maskPattern(`${i}`)},maskMoney:i=>{d(c).maskMoney(i)}}};window.FilamentMaskInput=P;})(); diff --git a/jasmine.json b/jasmine.json new file mode 100644 index 0000000..428264e --- /dev/null +++ b/jasmine.json @@ -0,0 +1,13 @@ +{ + "spec_dir": "resources/js/tests", + "spec_files": [ + "**/*[sS]pec.?(m)js" + ], + "helpers": [ + "resources/js/tests/helpers/**/*.?(m)js" + ], + "env": { + "stopSpecOnExpectationFailure": false, + "random": false + } +} diff --git a/package.json b/package.json index 0fe4fb2..8fd900b 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,13 @@ "author": "Rodrigo Fernandes ", "license": "MIT", "scripts": { - "build:scripts": "node bin/build.js" + "build:scripts": "node bin/build.js", + "test": "jasmine --config=jasmine.json --require=resources/js/tests/helpers/domjs.js" }, "devDependencies": { "esbuild": "^0.19.10", - "vanilla-masker": "^1.2.0" - } + "jasmine": "^5.1.0", + "jsdom": "^23.2.0" + }, + "dependencies": {} } diff --git a/resources/js/Component/maskinput.js b/resources/js/Component/maskinput.js index 31325d9..9683ff5 100644 --- a/resources/js/Component/maskinput.js +++ b/resources/js/Component/maskinput.js @@ -1,4 +1,6 @@ -import VMasker from 'vanilla-masker'; + +import VMasker from '../vendor/vanilla-masker'; + export default (elementId) => { const inputElement = document.getElementById(elementId); diff --git a/resources/js/tests/helpers/domjs.js b/resources/js/tests/helpers/domjs.js new file mode 100644 index 0000000..1a29ff0 --- /dev/null +++ b/resources/js/tests/helpers/domjs.js @@ -0,0 +1,10 @@ +import { JSDOM } from 'jsdom' + +const dom = new JSDOM(''); + + +global.document = dom.window.document; +global.window = dom.window; +global.KeyboardEvent = window.KeyboardEvent; +global.Event = window.Event; + diff --git a/resources/js/tests/money_spec.js b/resources/js/tests/money_spec.js new file mode 100644 index 0000000..4d2c4cd --- /dev/null +++ b/resources/js/tests/money_spec.js @@ -0,0 +1,93 @@ +import VMasker from '../vendor/vanilla-masker/index.js' + +describe("VanillaMasker.maskMoney", function() { + + it('throws error: "VanillaMasker: There is no element to bind." when element is undefined', function() { + expect(function() { + VMasker(undefined).maskMoney(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is null', function() { + expect(function() { + VMasker(null).maskMoney(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is blank', function() { + expect(function() { + VMasker("").maskMoney(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('does not throw error when element is empty array', function() { + expect(function() { + VMasker([]).maskMoney(); + }).not.toThrow(); + }); + +}); + +describe("VanillaMasker.toMoney", function() { + + it('returns the default money', function() { + expect(VMasker.toMoney('100000000,00')).toEqual('100000000,00'); + }); + + it('returns 0,00 money when number is 0', function() { + expect(VMasker.toMoney('0')).toEqual('0'); + }); + + it('returns 0,01 money when number is 1', function() { + expect(VMasker.toMoney('0,01')).toEqual('0,01'); + }); + + it('returns 0,10 default money number is 10', function() { + expect(VMasker.toMoney('0,10')).toEqual('0,10'); + }); + + it('returns 1.000 money when precision is 0', function() { + expect(VMasker.toMoney(1000, {decimalPrecision: 0})).toEqual('1.000'); + }); + + it('returns 100,000,000,00 when delimiter is ","', function() { + expect(VMasker.toMoney('100000000,00', {decimalSeparator: ',', thousandsSeparator: '.'})).toEqual('100000000,00'); + }); + + it('returns 100.000.000.00 when separator is "."', function() { + expect(VMasker.toMoney( '100000000.00', {decimalSeparator: '.', thousandsSeparator:','})).toEqual('100000000.00'); + }); + + it('returns 100.000.000 is true', function() { + expect(VMasker.toMoney(100000000)).toEqual('100.000.000'); + }); + + it('returns -3,75 when showSignal is true and given a float value', function() { + expect(VMasker.toMoney(-375, {allowNegative: true})).toEqual('-375'); + }); + + it('returns 3,75 when showSignal is false and given a float value', function() { + expect(VMasker.toMoney(-375, {allowNegative: false})).toEqual('375'); + }); + + it('returns -3,75 when allowNegative is true and given a string value', function() { + expect(VMasker.toMoney('-3,75', {allowNegative: true})).toEqual('-3,75'); + }); + + it('returns 12,000 when value is 12,000 and precision is 3', function() { + expect(VMasker.toMoney('12,000', {decimalPrecision: 3})).toEqual('12,000'); + }); + + it('returns 123,0000 when value is 123,0000 and precision is 4', function() { + expect(VMasker.toMoney('123,0000', {decimalPrecision: 4})).toEqual('123,0000'); + }); + + it('returns 123,00000 when value is 123,00000 and precision is 5', function() { + expect(VMasker.toMoney('123,00000', {decimalPrecision: 5})).toEqual('123,00000'); + }); + + it('parses proper precision location from strings', function() { + expect(VMasker.toMoney('1,20', {decimalPrecision: 2})).toEqual('1,20'); + }); + +}); diff --git a/resources/js/tests/number_spec.js b/resources/js/tests/number_spec.js new file mode 100644 index 0000000..da65888 --- /dev/null +++ b/resources/js/tests/number_spec.js @@ -0,0 +1,49 @@ +import VMasker from '../vendor/vanilla-masker/index.js' + +describe("VanillaMasker.maskNumber", function() { + + it('throws error: "VanillaMasker: There is no element to bind." when element is undefined', function() { + expect(function() { + VMasker(undefined).maskNumber(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is null', function() { + expect(function() { + VMasker(null).maskNumber(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is blank', function() { + expect(function() { + VMasker("").maskNumber(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('does not throw error when element is empty array', function() { + expect(function() { + VMasker([]).maskNumber(); + }).not.toThrow(); + }); + +}); + +describe("VanillaMasker.toNumber", function() { + + it('returns 1000 number when input is 1000', function() { + expect(VMasker.toNumber(1000)).toEqual('1000'); + }); + + it('returns 100000 number when input is 1a0b0c000', function() { + expect(VMasker.toNumber('1a0b0c000')).toEqual('100000'); + }); + + it('returns 10 number when input is 1-0', function() { + expect(VMasker.toNumber('1-0')).toEqual('10'); + }); + + it('returns -10 number when input is -10', function() { + expect(VMasker.toNumber('-10')).toEqual('-10'); + }); + +}); diff --git a/resources/js/tests/pattern_spec.js b/resources/js/tests/pattern_spec.js new file mode 100644 index 0000000..6647a2e --- /dev/null +++ b/resources/js/tests/pattern_spec.js @@ -0,0 +1,117 @@ +import VMasker from '../vendor/vanilla-masker/index.js' + +describe("VanillaMasker.maskPattern", function() { + + it('throws error: "VanillaMasker: There is no element to bind." when element is undefined', function() { + expect(function() { + VMasker(undefined).maskPattern(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is null', function() { + expect(function() { + VMasker(null).maskPattern(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('throws error: "VanillaMasker: There is no element to bind." when element is blank', function() { + expect(function() { + VMasker("").maskPattern(); + }).toThrow(new Error('VanillaMasker: There is no element to bind.')); + }); + + it('does not throw error when element is empty array', function() { + expect(function() { + VMasker([]).maskPattern(); + }).not.toThrow(); + }); + +}); + +describe("VanillaMasker.toPattern", function() { + + it('returns "(61)" pattern when input is 61', function() { + expect(VMasker.toPattern(61, '(99)')).toEqual('(61)'); + }); + + it('returns "(61) 91234-5678" pattern when input is 61912345678', function() { + expect(VMasker.toPattern(61912345678, '(99) 99999-9999')).toEqual('(61) 91234-5678'); + }); + + it('returns "(10) 9991-1111" pattern when input is 1099911111', function() { + expect(VMasker.toPattern(1099911111, '(99) 9999-9999')).toEqual('(10) 9991-1111'); + }); + + it('returns "(10) 11" pattern when input is 1011', function() { + expect(VMasker.toPattern('1011', '(99) 9999-9999')).toEqual('(10) 11'); + }); + + it('returns "+10 11 4444-44" pattern when input is 1011444444', function() { + expect(VMasker.toPattern('1011444444', '+99 99 9999-99')).toEqual('+10 11 4444-44'); + }); + + it('returns "+1 (888) 888-8888" pattern when input is 8888888888', function() { + expect(VMasker.toPattern('8888888888', '+1 (999) 999-9999')).toEqual('+1 (888) 888-8888'); + }); + + it('returns "+1 (888) 888-8" pattern when input is 8888888', function() { + expect(VMasker.toPattern('8888888', '+1 (999) 999-9999')).toEqual('+1 (888) 888-8'); + }); + it('returns "+1 (888) 888-8" pattern when input is +1 (888) 888-8', function() { + expect(VMasker.toPattern('+1 (888) 888-8', '+1 (999) 999-9999')).toEqual('+1 (888) 888-8'); + }); + + it('returns "12/12/2000" pattern when input is 12122000', function() { + expect(VMasker.toPattern(12122000, '99/99/9999')).toEqual('12/12/2000'); + }); + + it('returns "10/11" pattern when input is 1011', function() { + expect(VMasker.toPattern('1011', '99/99/9999')).toEqual('10/11'); + }); + + it('returns "2000/12/12" pattern when input is 20001212', function() { + expect(VMasker.toPattern('20001212', '9999/99/99')).toEqual('2000/12/12'); + }); + + it('returns "999.111.111-01" pattern when input is 99911111101', function() { + expect(VMasker.toPattern(99911111101, '999.999.999-99')).toEqual('999.111.111-01'); + }); + + it('returns "101.1" pattern when input is 1011', function() { + expect(VMasker.toPattern('1011', '999.999.999-99')).toEqual('101.1'); + }); + + it('returns "ABC-1234" pattern when input is ABC1234', function() { + expect(VMasker.toPattern('ABC1234', 'AAA-1234')).toEqual('ABC-1234'); + }); + + it('returns incomplete result: "AB" when input is AB1 and pattern is AAA-99', function() { + expect(VMasker.toPattern('AB1', 'AAA-99')).toEqual('AB'); + }); + + it('returns "9B.GR.D08X0.4.G.117974" pattern when input is 9BGRD08X04G117974', function() { + expect(VMasker.toPattern('9BGRD08X04G117974', 'SS.SS.SSSSS.S.S.SSSSSS')).toEqual('9B.GR.D08X0.4.G.117974'); + }); + + it('returns "BB.G" pattern when input is 9BG', function() { + expect(VMasker.toPattern('BBG', 'SS.SS.SSSSS.S.S.SSSSSS')).toEqual('BB.G'); + }); + + it('returns "(4xx) xxx-xxxx" when input is 4 and placeholder is x', function(){ + expect(VMasker.toPattern('4', {pattern: "(999) 999-9999", placeholder: "x"})).toEqual('(4xx) xxx-xxxx'); + }); + + it('returns "(___) ___-_____" when input is empty and placeholder is _', function(){ + expect(VMasker.toPattern('', {pattern: "(999) 999-9999", placeholder: "_"})).toEqual('(___) ___-____'); + }); + + it('returns "(111) 111-1111" when input is 1111111111 and placeholder is _', function(){ + expect(VMasker.toPattern('1111111111', {pattern: "(999) 999-9999", placeholder: "_"})).toEqual('(111) 111-1111'); + }); + + it('returns "(aaa) _____" when input is aaa999aaaa and placeholder is _', function(){ + expect(VMasker.toPattern('aaa999aaaa', {pattern: "(AAA) AAAAA", placeholder: "_"})).toEqual('(aaa) _____'); + }); + + +}); diff --git a/resources/js/vendor/vanilla-masker/index.js b/resources/js/vendor/vanilla-masker/index.js new file mode 100644 index 0000000..ef0d24c --- /dev/null +++ b/resources/js/vendor/vanilla-masker/index.js @@ -0,0 +1,204 @@ +export default (() => { + const DIGIT = "9", + ALPHA = "A", + ALPHANUM = "S", + BY_PASS_KEYS = [9, 16, 17, 18, 36, 37, 38, 39, 40, 91, 92, 93], + isAllowedKeyCode = function (keyCode) { + for (let i = 0, len = BY_PASS_KEYS.length; i < len; i++) { + if (keyCode === BY_PASS_KEYS[i]) { + return false; + } + } + return true; + }, + mergeMoneyOptions = function (opts) { + opts = opts || {}; + opts = { + thousandsSeparator: opts.hasOwnProperty("thousandsSeparator") ? opts.thousandsSeparator : ".", + lastOutput: opts.lastOutput, + decimalPrecision: opts.hasOwnProperty("decimalPrecision") ? opts.decimalPrecision : 2, + decimalSeparator: opts.decimalSeparator || ",", + allowNegative: Boolean(opts.allowNegative) || false + }; + + return opts; + }, + // Fill wildcards past index in output with placeholder + addPlaceholdersToOutput = function (output, index, placeholder) { + for (; index < output.length; index++) { + if (output[index] === DIGIT || output[index] === ALPHA || output[index] === ALPHANUM) { + output[index] = placeholder; + } + } + return output; + }; + + const VanillaMasker = function (elements) { + this.elements = elements; + }; + + VanillaMasker.prototype.unbindElementToMask = function () { + const that = this; + + for (let i = 0, len = this.elements.length; i < len; i++) { + this.elements[i].lastOutput = ""; + this.elements[i].onkeyup = false; + this.elements[i].onkeydown = false; + + if (this.elements[i].value.length) { + this.elements[i].value = this.elements[i].value.replace(/\D/g, ''); + } + } + }; + + VanillaMasker.prototype.bindElementToMask = function (maskFunction) { + const that = this, + onType = function (event) { + //e = e || window.event; + const source = event.currentTarget; + + if (isAllowedKeyCode(event.keyCode)) { + setTimeout(function () { + that.opts.lastOutput = source.lastOutput; + source.value = VMasker[maskFunction](source.value, that.opts); + source.lastOutput = source.value; + }, 0); + } + } + ; + + for (let i = 0, len = this.elements.length; i < len; i++) { + this.elements[i].lastOutput = ""; + this.elements[i].onkeyup = onType; + if (this.elements[i].value.length) { + this.elements[i].value = VMasker[maskFunction](this.elements[i].value, this.opts); + } + } + }; + + VanillaMasker.prototype.maskMoney = function (opts) { + this.opts = mergeMoneyOptions(opts); + this.bindElementToMask("toMoney"); + }; + + VanillaMasker.prototype.maskNumber = function () { + this.opts = {}; + this.bindElementToMask("toNumber"); + }; + + VanillaMasker.prototype.maskAlphaNum = function () { + this.opts = {}; + this.bindElementToMask("toAlphaNumeric"); + }; + + VanillaMasker.prototype.maskPattern = function (pattern) { + this.opts = {pattern: pattern}; + this.bindElementToMask("toPattern"); + }; + + VanillaMasker.prototype.unMask = function () { + this.unbindElementToMask(); + }; + + const VMasker = function (el) { + if (!el) { + throw new Error("VanillaMasker: There is no element to bind."); + } + const elements = ("length" in el) ? (el.length ? el : []) : [el]; + return new VanillaMasker(elements); + }; + + VMasker.toMoney = function (value, opts) { + + opts = mergeMoneyOptions(opts); + + let number = String(value); + + if (number.includes(opts.decimalSeparator)) { + + let [integer, decimal] = number.split(opts.decimalSeparator); + + if (decimal && decimal.length > opts.decimalPrecision) { + decimal = decimal.substring(0, opts.decimalPrecision); + } + + number = integer + opts.decimalSeparator + decimal; + + return number; + } + + let negativeSignal = "" + + + if (opts.allowNegative === true){ + negativeSignal = "(^[^-]?)|"; + } + + number = number.replace(new RegExp(negativeSignal + `([^0-9\\${opts.thousandsSeparator}\\${opts.decimalSeparator}])`, "g"), ''); + + number = number.replace(new RegExp(`\\${opts.thousandsSeparator}`, "g"), '').replace(new RegExp(`\\${opts.decimalSeparator}`, "g"), opts.thousandsSeparator); + + let [integer, decimal] = number.split(opts.thousandsSeparator); + + integer = integer.replace(/\B(?=(\d{3})+(?!\d))/g, opts.thousandsSeparator); + + number = integer + (decimal ? opts.decimalSeparator + decimal : ''); + + return number; + }; + + VMasker.toPattern = function (value, opts) { + const pattern = (typeof opts === 'object' ? opts.pattern : opts), + patternChars = pattern.replace(/\W/g, ''), + output = pattern.split(""), + values = value.toString().replace(/\W/g, ""), + charsValues = values.replace(/\W/g, ''), + outputLength = output.length, + placeholder = (typeof opts === 'object' ? opts.placeholder : undefined); + + let index = 0, + i; + + for (i = 0; i < outputLength; i++) { + // Reached the end of input + if (index >= values.length) { + if (patternChars.length === charsValues.length) { + return output.join(""); + } else if ((placeholder !== undefined) && (patternChars.length > charsValues.length)) { + return addPlaceholdersToOutput(output, i, placeholder).join(""); + } else { + break; + } + } + // Remaining chars in input + else { + if ((output[i] === DIGIT && values[index].match(/[0-9]/)) || + (output[i] === ALPHA && values[index].match(/[a-zA-Z]/)) || + (output[i] === ALPHANUM && values[index].match(/[0-9a-zA-Z]/))) { + output[i] = values[index++]; + } else if (output[i] === DIGIT || output[i] === ALPHA || output[i] === ALPHANUM) { + if (placeholder !== undefined) { + return addPlaceholdersToOutput(output, i, placeholder).join(""); + } else { + return output.slice(0, i).join(""); + } + // exact match for a non-magic character + } else if (output[i] === values[index]) { + index++; + } + + } + } + return output.join("").slice(0, i); + }; + + VMasker.toNumber = function (value) { + return value.toString().replace(/(?!^-)[^0-9]/g, ""); + }; + + VMasker.toAlphaNumeric = function (value) { + return value.toString().replace(/[^a-z0-9 ]+/i, ""); + }; + + return VMasker; +})(); diff --git a/src/Components/MaskInput.php b/src/Components/MaskInput.php index 5314c41..cfc769b 100644 --- a/src/Components/MaskInput.php +++ b/src/Components/MaskInput.php @@ -7,7 +7,6 @@ use Filament\Support\RawJs; use Illuminate\Contracts\View\View; use Illuminate\Support\Str; -use Illuminate\Support\Stringable; use Rodrigofs\FilamentMaskInput\Emun\MaskType; use Rodrigofs\FilamentMaskInput\Exception\FilamentMaskInputException; @@ -20,31 +19,24 @@ class MaskInput extends TextInput protected ?RawJs $money = null; /** - * @param int|null $precision Decimal precision - * @param string|null $separator Decimal separator - * @param string|null $delimiter Number delimiter - * @param string|null $unit Money unit -> 'R$ 12.345.678,90' - * @param string|null $suffixUnit Money unit -> '12.345.678,90 R$' - * @param bool $zeroCents Force type only number instead decimal, masking decimals with ",00" Zero cents -> 'R$ 1.234.567.890,00' + * @param int|null $decimalPrecision Precision decimal + * @param string|null $decimalSeparator Decimal separator + * @param string|null $thousandsSeparator Thousands separator + * @param bool | null $allowNegative Allow negative numbers * @return $this */ - public function money(?int $precision = null, ?string $separator = null, ?string $delimiter = null, ?string $unit = null, ?string $suffixUnit = null, ?bool $zeroCents = null): static + public function money(?int $decimalPrecision = null, ?string $decimalSeparator = null, ?string $thousandsSeparator = null, ?bool $allowNegative = false): static { - - $suffixUnit = $suffixUnit ?? config('filament-maskinput.suffixUnit'); - $zeroCents = $zeroCents ?? config('filament-maskinput.zeroCents'); - $precision = $precision ?? config('filament-maskinput.precision'); - $separator = $separator ?? config('filament-maskinput.separator'); - $delimiter = $delimiter ?? config('filament-maskinput.delimiter'); - $unit = $unit ?? config('filament-maskinput.unit'); + $decimalPrecision = $decimalPrecision ?? config('filament-maskinput.decimalPrecision'); + $thousandsSeparator = $thousandsSeparator ?? config('filament-maskinput.thousandsSeparator'); + $decimalSeparator = $decimalSeparator ?? config('filament-maskinput.decimalSeparator'); + $allowNegative = $allowNegative ?? config('filament-maskinput.allowNegative'); $json = Str::of('{') - ->when($suffixUnit, fn (Stringable $string): Stringable => $string->append("suffixUnit: '{$suffixUnit}',")) - ->when($zeroCents, fn (Stringable $string): Stringable => $string->append('zeroCents: true,')) - ->append("precision: {$precision},") - ->append("separator: '{$separator}',") - ->append("delimiter: '{$delimiter}',") - ->append("unit: '{$unit}'") + ->append("decimalPrecision: {$decimalPrecision},") + ->append("thousandsSeparator: '{$thousandsSeparator}',") + ->append("decimalSeparator: '{$decimalSeparator}',") + ->append("allowNegative: '{$allowNegative}'") ->finish('}'); $this->maskType = MaskType::MONEY; diff --git a/yarn.lock b/yarn.lock index 58c9f16..9e481fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,15 @@ # yarn lockfile v1 +"@asamuzakjp/dom-selector@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@asamuzakjp/dom-selector/-/dom-selector-2.0.1.tgz#26dd05c504faa95a200a780f192fc9ca9feaa67e" + integrity sha512-QJAJffmCiymkv6YyQ7voyQb5caCth6jzZsQncYCpHXrJ7RqdYG5y43+is8mnFcYubdOkr7cn1+na9BdFMxqw7w== + dependencies: + bidi-js "^1.0.3" + css-tree "^2.3.1" + is-potential-custom-element-name "^1.0.1" + "@esbuild/aix-ppc64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz#2acd20be6d4f0458bc8c784103495ff24f13b1d3" @@ -117,6 +126,164 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bidi-js@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" + integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== + dependencies: + require-from-string "^2.0.2" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-tree@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +cssstyle@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.0.1.tgz#ef29c598a1e90125c870525490ea4f354db0660a" + integrity sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ== + dependencies: + rrweb-cssom "^0.6.0" + +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== + dependencies: + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + +debug@4, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decimal.js@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + esbuild@^0.19.10: version "0.19.11" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96" @@ -146,7 +313,388 @@ esbuild@^0.19.10: "@esbuild/win32-ia32" "0.19.11" "@esbuild/win32-x64" "0.19.11" -vanilla-masker@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vanilla-masker/-/vanilla-masker-1.2.0.tgz#c2830e9d994a5fecd2261506477c2707fe589756" - integrity sha512-5SQeksiWaRYfbTaLVcqDPlvINGRt7ODbmWqqMMdT4GuZEC01KJm7FxaytscI5GZ9mlkTNQDwqllSHbv1ENxQEA== +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +glob@^10.2.2: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== + dependencies: + whatwg-encoding "^3.1.1" + +http-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jasmine-core@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-5.1.1.tgz#38b6ccfbe60aa2a863cf441751d9639b5a571edc" + integrity sha512-UrzO3fL7nnxlQXlvTynNAenL+21oUQRlzqQFsA2U11ryb4+NLOCOePZ70PTojEaUKhiFugh7dG0Q+I58xlPdWg== + +jasmine@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-5.1.0.tgz#a3218fd425ff35aec12f3dc6cf70d8cebbf0042a" + integrity sha512-prmJlC1dbLhti4nE4XAPDWmfJesYO15sjGXVp7Cs7Ym5I9Xtwa/hUHxxJXjnpfLO72+ySttA0Ztf8g/RiVnUKw== + dependencies: + glob "^10.2.2" + jasmine-core "~5.1.0" + +jsdom@^23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-23.2.0.tgz#08083220146d41c467efa1c6969f02b525ba6c1d" + integrity sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA== + dependencies: + "@asamuzakjp/dom-selector" "^2.0.1" + cssstyle "^4.0.1" + data-urls "^5.0.0" + decimal.js "^10.4.3" + form-data "^4.0.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.2" + is-potential-custom-element-name "^1.0.1" + parse5 "^7.1.2" + rrweb-cssom "^0.6.0" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.3" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + ws "^8.16.0" + xml-name-validator "^5.0.0" + +"lru-cache@^9.1.1 || ^10.0.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +parse5@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.1, punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +rrweb-cssom@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" + integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +source-map-js@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: + name string-width-cjs + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + name strip-ansi-cjs + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +tough-cookie@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.0.0.tgz#3b46d583613ec7283020d79019f1335723801cec" + integrity sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g== + dependencies: + punycode "^2.3.1" + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + +whatwg-url@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.0.0.tgz#00baaa7fd198744910c4b1ef68378f2200e4ceb6" + integrity sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw== + dependencies: + tr46 "^5.0.0" + webidl-conversions "^7.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +ws@^8.16.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== + +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==