Revert "revert 3729"

This reverts commit dbba06026c.
This commit is contained in:
Dan Harrin
2022-08-31 07:32:43 +01:00
parent 6105821562
commit d3ead95388
82 changed files with 1854 additions and 804 deletions
+18 -30
View File
@@ -1,34 +1,22 @@
const esbuild = require('esbuild')
const shouldWatch = process.argv.includes('--watch')
esbuild
.build({
define: {
'process.env.NODE_ENV': shouldWatch
? `'production'`
: `'development'`,
},
entryPoints: ['packages/forms/resources/js/index.js'],
outfile: 'packages/forms/dist/module.esm.js',
bundle: true,
platform: 'neutral',
mainFields: ['module', 'main'],
watch: shouldWatch,
})
.catch(() => process.exit(1))
const packages = ['forms', 'notifications']
esbuild
.build({
define: {
'process.env.NODE_ENV': shouldWatch
? `'production'`
: `'development'`,
},
entryPoints: ['packages/notifications/resources/js/index.js'],
outfile: 'packages/notifications/dist/module.esm.js',
bundle: true,
platform: 'neutral',
mainFields: ['module', 'main'],
watch: shouldWatch,
})
.catch(() => process.exit(1))
packages.forEach((package) => {
esbuild
.build({
define: {
'process.env.NODE_ENV': shouldWatch
? `'production'`
: `'development'`,
},
entryPoints: [`packages/${package}/resources/js/index.js`],
outfile: `packages/${package}/dist/module.esm.js`,
bundle: true,
platform: 'neutral',
mainFields: ['module', 'main'],
watch: shouldWatch,
})
.catch(() => process.exit(1))
})
+189 -189
View File
@@ -9,7 +9,7 @@
"@alpinejs/collapse": "^3.8.1",
"@alpinejs/focus": "^3.8.1",
"@alpinejs/persist": "^3.8.1",
"@awcodes/alpine-floating-ui": "^3.3.1",
"@awcodes/alpine-floating-ui": "^3.4.0",
"@babel/runtime": "^7.15.3",
"@danharrin/alpine-mousetrap": "^0.1.0",
"@github/file-attachment-element": "^2.0.1",
@@ -81,9 +81,9 @@
}
},
"node_modules/@awcodes/alpine-floating-ui": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@awcodes/alpine-floating-ui/-/alpine-floating-ui-3.3.1.tgz",
"integrity": "sha512-BPcBObA76AXPyY1f0S0xgrQXBLBCYGnHSH4BOb2kz0GZ31kNZ1kW/QcuXS3r+L006mzvgjYWehjCPmMTGDXPGw==",
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@awcodes/alpine-floating-ui/-/alpine-floating-ui-3.4.0.tgz",
"integrity": "sha512-D2XnqKAqN1w9q4rGnz1bG4bVE9kh8jVYpbBAT8jtvQ7jeadevW3g+NIV/CCljGdH3N8LmoYoyBfAtLYzDesXdw==",
"dev": true
},
"node_modules/@babel/code-frame": {
@@ -99,30 +99,30 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.18.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
"integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
"integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
"integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
"integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.18.13",
"@babel/helper-compilation-targets": "^7.18.9",
"@babel/helper-module-transforms": "^7.18.9",
"@babel/helpers": "^7.18.9",
"@babel/parser": "^7.18.10",
"@babel/parser": "^7.18.13",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.18.10",
"@babel/types": "^7.18.10",
"@babel/traverse": "^7.18.13",
"@babel/types": "^7.18.13",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -147,12 +147,12 @@
}
},
"node_modules/@babel/generator": {
"version": "7.18.12",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
"integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
"integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
"dev": true,
"dependencies": {
"@babel/types": "^7.18.10",
"@babel/types": "^7.18.13",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@@ -227,9 +227,9 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
"integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz",
"integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.18.6",
@@ -602,9 +602,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
"integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
"integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz",
"integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz",
"integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.9"
@@ -1764,19 +1764,19 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
"integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
"integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.18.13",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.18.9",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.18.11",
"@babel/types": "^7.18.10",
"@babel/parser": "^7.18.13",
"@babel/types": "^7.18.13",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1785,9 +1785,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
"integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
"integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
"dev": true,
"dependencies": {
"@babel/helper-string-parser": "^7.18.10",
@@ -1897,9 +1897,9 @@
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
"version": "0.3.15",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
"integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
@@ -1948,9 +1948,9 @@
}
},
"node_modules/@popperjs/core": {
"version": "2.11.5",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
"integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"dev": true,
"funding": {
"type": "opencollective",
@@ -2031,9 +2031,9 @@
}
},
"node_modules/@types/babel__traverse": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.0.tgz",
"integrity": "sha512-v4Vwdko+pgymgS+A2UIaJru93zQd85vIGWObM5ekZNdXCKtDYqATlEYnWgfo86Q6I1Lh0oXnksDnMU1cwmlPDw==",
"version": "7.18.1",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.1.tgz",
"integrity": "sha512-FSdLaZh2UxaMuLp9lixWaHq/golWTRWOnRsAXzDTDSDOQLuZb1nsdCt6pJSPWSEQt2eFZ2YVk3oYhn+1kLMeMA==",
"dev": true,
"dependencies": {
"@babel/types": "^7.3.0"
@@ -2088,9 +2088,9 @@
}
},
"node_modules/@types/eslint": {
"version": "8.4.5",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz",
"integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==",
"version": "8.4.6",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
"integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==",
"dev": true,
"dependencies": {
"@types/estree": "*",
@@ -2214,15 +2214,15 @@
"dev": true
},
"node_modules/@types/minimatch": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.1.tgz",
"integrity": "sha512-v55NF6Dz0wrj14Rn8iEABTWrhYRmgkJYuokduunSiq++t3hZ9VZ6dvcDt+850Pm5sGJZk8RaHzkFCXPxVINZ+g==",
"dev": true
},
"node_modules/@types/node": {
"version": "18.6.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.4.tgz",
"integrity": "sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==",
"version": "18.7.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
"dev": true
},
"node_modules/@types/parse-json": {
@@ -3218,9 +3218,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"version": "1.0.30001385",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001385.tgz",
"integrity": "sha512-MpiCqJGhBkHgpyimE9GWmZTnyHyEEM35u115bD3QBrXpjvL/JgcP8cUhKJshfmg4OtEHFenifcK5sZayEw5tvQ==",
"dev": true,
"funding": [
{
@@ -3398,9 +3398,9 @@
"dev": true
},
"node_modules/colord": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz",
"integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==",
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
"dev": true
},
"node_modules/colorette": {
@@ -3589,9 +3589,9 @@
"dev": true
},
"node_modules/core-js-compat": {
"version": "3.24.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz",
"integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==",
"version": "3.25.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz",
"integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==",
"dev": true,
"dependencies": {
"browserslist": "^4.21.3",
@@ -3848,9 +3848,9 @@
}
},
"node_modules/cssnano": {
"version": "5.1.12",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz",
"integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==",
"version": "5.1.13",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz",
"integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==",
"dev": true,
"dependencies": {
"cssnano-preset-default": "^5.2.12",
@@ -3936,9 +3936,9 @@
}
},
"node_modules/dayjs": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz",
"integrity": "sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g==",
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
"integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==",
"dev": true
},
"node_modules/debug": {
@@ -4188,9 +4188,9 @@
}
},
"node_modules/dompurify": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz",
"integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==",
"dev": true
},
"node_modules/domutils": {
@@ -4254,9 +4254,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.211",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.211.tgz",
"integrity": "sha512-BZSbMpyFQU0KBJ1JG26XGeFI3i4op+qOYGxftmZXFZoHkhLgsSv4DHDJfl8ogII3hIuzGt51PaZ195OVu0yJ9A==",
"version": "1.4.235",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.235.tgz",
"integrity": "sha512-eNU2SmVZYTzYVA5aAWmhAJbdVil5/8H5nMq6kGD0Yxd4k2uKIuT8YmS46I0QXY7iOoPPcb6jjem9/2xyuH5+XQ==",
"dev": true
},
"node_modules/elliptic": {
@@ -6097,9 +6097,9 @@
}
},
"node_modules/marked": {
"version": "4.0.18",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz",
"integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz",
"integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==",
"dev": true,
"bin": {
"marked": "bin/marked.js"
@@ -6555,9 +6555,9 @@
}
},
"node_modules/object.assign": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
"integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
@@ -8426,9 +8426,9 @@
}
},
"node_modules/std-env": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.1.1.tgz",
"integrity": "sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.2.1.tgz",
"integrity": "sha512-D/uYFWkI/31OrnKmXZqGAGK5GbQRPp/BWA1nuITcc6ICblhhuQUPHS5E2GSCVS7Hwhf4ciq8qsATwBUxv+lI6w==",
"dev": true
},
"node_modules/stream-browserify": {
@@ -8685,9 +8685,9 @@
}
},
"node_modules/terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
"integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
@@ -8703,16 +8703,16 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
"integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==",
"version": "5.3.6",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz",
"integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.7",
"@jridgewell/trace-mapping": "^0.3.14",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.0",
"terser": "^5.7.2"
"terser": "^5.14.1"
},
"engines": {
"node": ">= 10.13.0"
@@ -9273,9 +9273,9 @@
}
},
"node_modules/webpack-dev-server": {
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz",
"integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==",
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz",
"integrity": "sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw==",
"dev": true,
"dependencies": {
"@types/bonjour": "^3.5.9",
@@ -9669,9 +9669,9 @@
}
},
"@awcodes/alpine-floating-ui": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@awcodes/alpine-floating-ui/-/alpine-floating-ui-3.3.1.tgz",
"integrity": "sha512-BPcBObA76AXPyY1f0S0xgrQXBLBCYGnHSH4BOb2kz0GZ31kNZ1kW/QcuXS3r+L006mzvgjYWehjCPmMTGDXPGw==",
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@awcodes/alpine-floating-ui/-/alpine-floating-ui-3.4.0.tgz",
"integrity": "sha512-D2XnqKAqN1w9q4rGnz1bG4bVE9kh8jVYpbBAT8jtvQ7jeadevW3g+NIV/CCljGdH3N8LmoYoyBfAtLYzDesXdw==",
"dev": true
},
"@babel/code-frame": {
@@ -9684,27 +9684,27 @@
}
},
"@babel/compat-data": {
"version": "7.18.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
"integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
"integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
"dev": true
},
"@babel/core": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
"integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
"integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
"dev": true,
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.18.13",
"@babel/helper-compilation-targets": "^7.18.9",
"@babel/helper-module-transforms": "^7.18.9",
"@babel/helpers": "^7.18.9",
"@babel/parser": "^7.18.10",
"@babel/parser": "^7.18.13",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.18.10",
"@babel/types": "^7.18.10",
"@babel/traverse": "^7.18.13",
"@babel/types": "^7.18.13",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -9721,12 +9721,12 @@
}
},
"@babel/generator": {
"version": "7.18.12",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
"integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
"integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
"dev": true,
"requires": {
"@babel/types": "^7.18.10",
"@babel/types": "^7.18.13",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@@ -9784,9 +9784,9 @@
}
},
"@babel/helper-create-class-features-plugin": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
"integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz",
"integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.18.6",
@@ -10070,9 +10070,9 @@
}
},
"@babel/parser": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
"integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
"integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==",
"dev": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -10453,9 +10453,9 @@
}
},
"@babel/plugin-transform-destructuring": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz",
"integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz",
"integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.9"
@@ -10852,27 +10852,27 @@
}
},
"@babel/traverse": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
"integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
"integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.18.13",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.18.9",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.18.11",
"@babel/types": "^7.18.10",
"@babel/parser": "^7.18.13",
"@babel/types": "^7.18.13",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
"integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
"version": "7.18.13",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
"integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
"dev": true,
"requires": {
"@babel/helper-string-parser": "^7.18.10",
@@ -10963,9 +10963,9 @@
"dev": true
},
"@jridgewell/trace-mapping": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
"version": "0.3.15",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
"integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
@@ -11005,9 +11005,9 @@
}
},
"@popperjs/core": {
"version": "2.11.5",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
"integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"dev": true
},
"@ryangjchandler/alpine-tooltip": {
@@ -11075,9 +11075,9 @@
}
},
"@types/babel__traverse": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.0.tgz",
"integrity": "sha512-v4Vwdko+pgymgS+A2UIaJru93zQd85vIGWObM5ekZNdXCKtDYqATlEYnWgfo86Q6I1Lh0oXnksDnMU1cwmlPDw==",
"version": "7.18.1",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.1.tgz",
"integrity": "sha512-FSdLaZh2UxaMuLp9lixWaHq/golWTRWOnRsAXzDTDSDOQLuZb1nsdCt6pJSPWSEQt2eFZ2YVk3oYhn+1kLMeMA==",
"dev": true,
"requires": {
"@babel/types": "^7.3.0"
@@ -11132,9 +11132,9 @@
}
},
"@types/eslint": {
"version": "8.4.5",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz",
"integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==",
"version": "8.4.6",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz",
"integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==",
"dev": true,
"requires": {
"@types/estree": "*",
@@ -11258,15 +11258,15 @@
"dev": true
},
"@types/minimatch": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.1.tgz",
"integrity": "sha512-v55NF6Dz0wrj14Rn8iEABTWrhYRmgkJYuokduunSiq++t3hZ9VZ6dvcDt+850Pm5sGJZk8RaHzkFCXPxVINZ+g==",
"dev": true
},
"@types/node": {
"version": "18.6.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.4.tgz",
"integrity": "sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==",
"version": "18.7.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.14.tgz",
"integrity": "sha512-6bbDaETVi8oyIARulOE9qF1/Qdi/23z6emrUh0fNJRUmjznqrixD4MpGDdgOFk5Xb0m2H6Xu42JGdvAxaJR/wA==",
"dev": true
},
"@types/parse-json": {
@@ -12097,9 +12097,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"version": "1.0.30001385",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001385.tgz",
"integrity": "sha512-MpiCqJGhBkHgpyimE9GWmZTnyHyEEM35u115bD3QBrXpjvL/JgcP8cUhKJshfmg4OtEHFenifcK5sZayEw5tvQ==",
"dev": true
},
"chalk": {
@@ -12230,9 +12230,9 @@
"dev": true
},
"colord": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz",
"integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==",
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
"dev": true
},
"colorette": {
@@ -12386,9 +12386,9 @@
"dev": true
},
"core-js-compat": {
"version": "3.24.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz",
"integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==",
"version": "3.25.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz",
"integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==",
"dev": true,
"requires": {
"browserslist": "^4.21.3",
@@ -12588,9 +12588,9 @@
"dev": true
},
"cssnano": {
"version": "5.1.12",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.12.tgz",
"integrity": "sha512-TgvArbEZu0lk/dvg2ja+B7kYoD7BBCmn3+k58xD0qjrGHsFzXY/wKTo9M5egcUCabPol05e/PVoIu79s2JN4WQ==",
"version": "5.1.13",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz",
"integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==",
"dev": true,
"requires": {
"cssnano-preset-default": "^5.2.12",
@@ -12652,9 +12652,9 @@
}
},
"dayjs": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz",
"integrity": "sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g==",
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
"integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==",
"dev": true
},
"debug": {
@@ -12841,9 +12841,9 @@
}
},
"dompurify": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.10.tgz",
"integrity": "sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz",
"integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA==",
"dev": true
},
"domutils": {
@@ -12897,9 +12897,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.4.211",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.211.tgz",
"integrity": "sha512-BZSbMpyFQU0KBJ1JG26XGeFI3i4op+qOYGxftmZXFZoHkhLgsSv4DHDJfl8ogII3hIuzGt51PaZ195OVu0yJ9A==",
"version": "1.4.235",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.235.tgz",
"integrity": "sha512-eNU2SmVZYTzYVA5aAWmhAJbdVil5/8H5nMq6kGD0Yxd4k2uKIuT8YmS46I0QXY7iOoPPcb6jjem9/2xyuH5+XQ==",
"dev": true
},
"elliptic": {
@@ -14284,9 +14284,9 @@
}
},
"marked": {
"version": "4.0.18",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz",
"integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz",
"integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==",
"dev": true
},
"md5": {
@@ -14636,9 +14636,9 @@
"dev": true
},
"object.assign": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
"integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
@@ -15991,9 +15991,9 @@
"dev": true
},
"std-env": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.1.1.tgz",
"integrity": "sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.2.1.tgz",
"integrity": "sha512-D/uYFWkI/31OrnKmXZqGAGK5GbQRPp/BWA1nuITcc6ICblhhuQUPHS5E2GSCVS7Hwhf4ciq8qsATwBUxv+lI6w==",
"dev": true
},
"stream-browserify": {
@@ -16179,9 +16179,9 @@
"dev": true
},
"terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz",
"integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
@@ -16205,16 +16205,16 @@
}
},
"terser-webpack-plugin": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
"integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==",
"version": "5.3.6",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz",
"integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==",
"dev": true,
"requires": {
"@jridgewell/trace-mapping": "^0.3.7",
"@jridgewell/trace-mapping": "^0.3.14",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.0",
"terser": "^5.7.2"
"terser": "^5.14.1"
},
"dependencies": {
"schema-utils": {
@@ -16637,9 +16637,9 @@
}
},
"webpack-dev-server": {
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz",
"integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==",
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz",
"integrity": "sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw==",
"dev": true,
"requires": {
"@types/bonjour": "^3.5.9",
+1 -1
View File
@@ -9,7 +9,7 @@
"@alpinejs/collapse": "^3.8.1",
"@alpinejs/focus": "^3.8.1",
"@alpinejs/persist": "^3.8.1",
"@awcodes/alpine-floating-ui": "^3.3.1",
"@awcodes/alpine-floating-ui": "^3.4.0",
"@babel/runtime": "^7.15.3",
"@danharrin/alpine-mousetrap": "^0.1.0",
"@github/file-attachment-element": "^2.0.1",
+11 -11
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -159,6 +159,12 @@ class ExampleServiceProvider extends PluginServiceProvider
}
```
#### Tailwind CSS
If you are using Tailwind classes, that are not used in Filament core, you need to compile your own Tailwind CSS file and bundle it with your plugin. Follow the Tailwind instructions for setup, but omit `@tailwind base` as this would overwrite the base styles if users customize their Filament theme.
After compilation, your Tailwind stylesheet may contain classes that are already used in Filament core. You should purge those classes with [awcodes/filament-plugin-purge](https://github.com/awcodes/filament-plugin-purge) to keep the stylesheets size low.
### Scripts
To include a custom script, add it to the `$scripts` property in your service provider. You should use a unique name as the key and the URL to the script as the value. These scripts will be added after the core Filament script.
-1
View File
@@ -1,6 +1,5 @@
import Alpine from 'alpinejs'
import Chart from 'chart.js/auto'
import Collapse from '@alpinejs/collapse'
import Focus from '@alpinejs/focus'
import FormsAlpinePlugin from '../../../forms/dist/module.esm'
@@ -0,0 +1,10 @@
@captureSlots([
'trigger',
])
<x-filament-support::dropdown
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->merge($slots)"
:dark-mode="config('filament.dark_mode')"
>
{{ $slot }}
</x-filament-support::dropdown>
@@ -2,123 +2,104 @@
$user = \Filament\Facades\Filament::auth()->user();
@endphp
<div
x-data="{
mode: null,
theme: null,
init: function () {
this.theme = localStorage.getItem('theme') || (this.isSystemDark() ? 'dark' : 'light')
this.mode = localStorage.getItem('theme') ? 'manual' : 'auto'
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
if (this.mode === 'manual') return
if (event.matches && (! document.documentElement.classList.contains('dark'))) {
this.theme = 'dark'
document.documentElement.classList.add('dark')
} else if ((! event.matches) && document.documentElement.classList.contains('dark')) {
this.theme = 'light'
document.documentElement.classList.remove('dark')
}
})
$watch('theme', () => {
if (this.mode === 'auto') return
localStorage.setItem('theme', this.theme)
if (this.theme === 'dark' && (! document.documentElement.classList.contains('dark'))) {
document.documentElement.classList.add('dark')
} else if (this.theme === 'light' && document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark')
}
$dispatch('dark-mode-toggled', this.theme)
})
},
isSystemDark: function () {
return window.matchMedia('(prefers-color-scheme: dark)').matches
},
}"
{{ $attributes->class(['relative']) }}
>
<button
x-on:click="$refs.panel.toggle"
class="block flex-shrink-0"
>
<x-filament::dropdown placement="bottom-end">
<x-slot name="trigger">
<x-filament::user-avatar :user="$user" />
</button>
</x-slot>
<div
x-ref="panel"
x-float.placement.bottom-end.offset="{ offset: 8 }"
x-transition:enter="transition"
x-transition:enter-start="-translate-y-1 opacity-0"
x-transition:enter-end="translate-y-0 opacity-100"
x-transition:leave="transition"
x-transition:leave-start="translate-y-0 opacity-100"
x-transition:leave-end="-translate-y-1 opacity-0"
x-cloak
class="absolute z-10 hidden shadow-xl rounded-xl w-52 top-full"
<ul
class="py-1 space-y-1"
x-data="{
mode: null,
theme: null,
init: function () {
this.theme = localStorage.getItem('theme') || (this.isSystemDark() ? 'dark' : 'light')
this.mode = localStorage.getItem('theme') ? 'manual' : 'auto'
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
if (this.mode === 'manual') return
if (event.matches && (! document.documentElement.classList.contains('dark'))) {
this.theme = 'dark'
document.documentElement.classList.add('dark')
} else if ((! event.matches) && document.documentElement.classList.contains('dark')) {
this.theme = 'light'
document.documentElement.classList.remove('dark')
}
})
$watch('theme', () => {
if (this.mode === 'auto') return
localStorage.setItem('theme', this.theme)
if (this.theme === 'dark' && (! document.documentElement.classList.contains('dark'))) {
document.documentElement.classList.add('dark')
} else if (this.theme === 'light' && document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark')
}
$dispatch('dark-mode-toggled', this.theme)
})
},
isSystemDark: function () {
return window.matchMedia('(prefers-color-scheme: dark)').matches
},
}"
>
<ul @class([
'py-1 space-y-1 overflow-hidden bg-white shadow rounded-xl',
'dark:border-gray-600 dark:bg-gray-700' => config('filament.dark_mode'),
])>
@php
$items = \Filament\Facades\Filament::getUserMenuItems();
$accountItem = $items['account'] ?? null;
$logoutItem = $items['logout'] ?? null;
@endphp
@php
$items = \Filament\Facades\Filament::getUserMenuItems();
$accountItem = $items['account'] ?? null;
$logoutItem = $items['logout'] ?? null;
@endphp
<x-filament::dropdown.item
:color="$accountItem?->getColor() ?? 'secondary'"
:icon="$accountItem?->getIcon() ?? 'heroicon-s-user-circle'"
:href="$accountItem?->getUrl()"
tag="a"
>
{{ $accountItem?->getLabel() ?? \Filament\Facades\Filament::getUserName($user) }}
</x-filament::dropdown.item>
<x-filament::dropdown.item
:color="$accountItem?->getColor() ?? 'secondary'"
:icon="$accountItem?->getIcon() ?? 'heroicon-s-user-circle'"
:href="$accountItem?->getUrl()"
tag="a"
>
{{ $accountItem?->getLabel() ?? \Filament\Facades\Filament::getUserName($user) }}
</x-filament::dropdown.item>
<div>
@if (config('filament.dark_mode'))
<x-filament::dropdown.item icon="heroicon-s-moon" x-show="theme === 'dark'" x-on:click="$refs.panel.close; mode = 'manual'; theme = 'light'">
{{ __('filament::layout.buttons.light_mode.label') }}
</x-filament::dropdown.item>
<div>
@if (config('filament.dark_mode'))
<x-filament::dropdown.item icon="heroicon-s-moon" x-show="theme === 'dark'" x-on:click="close(); mode = 'manual'; theme = 'light'">
{{ __('filament::layout.buttons.light_mode.label') }}
</x-filament::dropdown.item>
<x-filament::dropdown.item icon="heroicon-s-sun" x-show="theme === 'light'" x-on:click="$refs.panel.close; mode = 'manual'; theme = 'dark'">
{{ __('filament::layout.buttons.dark_mode.label') }}
</x-filament::dropdown.item>
@endif
</div>
<x-filament::dropdown.item icon="heroicon-s-sun" x-show="theme === 'light'" x-on:click="close(); mode = 'manual'; theme = 'dark'">
{{ __('filament::layout.buttons.dark_mode.label') }}
</x-filament::dropdown.item>
@endif
</div>
@foreach ($items as $key => $item)
@if ($key !== 'account' && $key !== 'logout')
<x-filament::dropdown.item
:color="$item->getColor() ?? 'secondary'"
:icon="$item->getIcon()"
:href="$item->getUrl()"
tag="a"
>
{{ $item->getLabel() }}
</x-filament::dropdown.item>
@endif
@endforeach
@foreach ($items as $key => $item)
@if ($key !== 'account' && $key !== 'logout')
<x-filament::dropdown.item
:color="$item->getColor() ?? 'secondary'"
:icon="$item->getIcon()"
:href="$item->getUrl()"
tag="a"
>
{{ $item->getLabel() }}
</x-filament::dropdown.item>
@endif
@endforeach
<x-filament::dropdown.item
:color="$logoutItem?->getColor() ?? 'secondary'"
:icon="$logoutItem?->getIcon() ?? 'heroicon-s-logout'"
:action="$logoutItem?->getUrl() ?? route('filament.auth.logout')"
method="post"
tag="form"
>
{{ $logoutItem?->getLabel() ?? __('filament::layout.buttons.logout.label') }}
</x-filament::dropdown.item>
</ul>
</div>
</div>
<x-filament::dropdown.item
:color="$logoutItem?->getColor() ?? 'secondary'"
:icon="$logoutItem?->getIcon() ?? 'heroicon-s-logout'"
:action="$logoutItem?->getUrl() ?? route('filament.auth.logout')"
method="post"
tag="form"
>
{{ $logoutItem?->getLabel() ?? __('filament::layout.buttons.logout.label') }}
</x-filament::dropdown.item>
</ul>
</x-filament::dropdown>
@@ -42,8 +42,6 @@
<link href="{{ $fontsUrl }}" rel="stylesheet" />
@endif
{{ \Filament\Facades\Filament::getThemeLink() }}
@foreach (\Filament\Facades\Filament::getStyles() as $name => $path)
@if (\Illuminate\Support\Str::of($path)->startsWith(['http://', 'https://']))
<link rel="stylesheet" href="{{ $path }}" />
@@ -56,6 +54,8 @@
@endif
@endforeach
{{ \Filament\Facades\Filament::getThemeLink() }}
{{ \Filament\Facades\Filament::renderHook('styles.end') }}
@if (config('filament.dark_mode'))
+3 -2
View File
@@ -12,6 +12,7 @@ use Filament\Models\Contracts\HasName;
use Filament\Navigation\NavigationGroup;
use Filament\Navigation\UserMenuItem;
use Filament\Notifications\Notification;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Model;
@@ -368,7 +369,7 @@ class FilamentManager
return $firstItem->getUrl();
}
public function getUserAvatarUrl(Model $user): string
public function getUserAvatarUrl(Model | Authenticatable $user): string
{
$avatar = null;
@@ -385,7 +386,7 @@ class FilamentManager
return app($provider)->get($user);
}
public function getUserName(Model $user): string
public function getUserName(Model | Authenticatable $user): string
{
if ($user instanceof HasName) {
return $user->getFilamentName();
@@ -29,12 +29,17 @@ class CreateRecord extends Page implements HasFormActions
}
public function mount(): void
{
$this->authorizeAccess();
$this->fillForm();
}
protected function authorizeAccess(): void
{
static::authorizeResourceAccess();
abort_unless(static::getResource()::canCreate(), 403);
$this->fillForm();
}
protected function fillForm(): void
@@ -48,6 +53,8 @@ class CreateRecord extends Page implements HasFormActions
public function create(bool $another = false): void
{
$this->authorizeAccess();
$this->callHook('beforeValidate');
$data = $this->form->getState();
@@ -37,14 +37,19 @@ class EditRecord extends Page implements HasFormActions
}
public function mount($record): void
{
$this->authorizeAccess($record);
$this->fillForm();
}
protected function authorizeAccess($record): void
{
static::authorizeResourceAccess();
$this->record = $this->resolveRecord($record);
abort_unless(static::getResource()::canEdit($this->getRecord()), 403);
$this->fillForm();
}
protected function fillForm(): void
@@ -67,6 +72,8 @@ class EditRecord extends Page implements HasFormActions
public function save(bool $shouldRedirect = true): void
{
$this->authorizeAccess($this->getRecord()->getKey());
$this->callHook('beforeValidate');
$data = $this->form->getState();
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace Livewire\Testing {
class TestableLivewire {
public function assertFormExists(string $name = 'form'): static {}
public function assertFormFieldExists(string $fieldName, string $formName = 'form'): static {}
public function assertFormFieldIsDisabled(string $fieldName, string $formName = 'form'): static {}
public function assertFormFieldIsEnabled(string $fieldName, string $formName = 'form'): static {}
public function assertFormFieldIsHidden(string $fieldName, string $formName = 'form'): static {}
public function assertFormFieldIsVisible(string $fieldName, string $formName = 'form'): static {}
}
}
+266 -74
View File
@@ -789,7 +789,7 @@ var require_fr = __commonJS((exports, module) => {
return e3 && typeof e3 == "object" && "default" in e3 ? e3 : {default: e3};
}
var t2 = n2(e2), i = {name: "fr", weekdays: "dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"), weekdaysShort: "dim._lun._mar._mer._jeu._ven._sam.".split("_"), weekdaysMin: "di_lu_ma_me_je_ve_sa".split("_"), months: "janvier_f\xE9vrier_mars_avril_mai_juin_juillet_ao\xFBt_septembre_octobre_novembre_d\xE9cembre".split("_"), monthsShort: "janv._f\xE9vr._mars_avr._mai_juin_juil._ao\xFBt_sept._oct._nov._d\xE9c.".split("_"), weekStart: 1, yearStart: 4, formats: {LT: "HH:mm", LTS: "HH:mm:ss", L: "DD/MM/YYYY", LL: "D MMMM YYYY", LLL: "D MMMM YYYY HH:mm", LLLL: "dddd D MMMM YYYY HH:mm"}, relativeTime: {future: "dans %s", past: "il y a %s", s: "quelques secondes", m: "une minute", mm: "%d minutes", h: "une heure", hh: "%d heures", d: "un jour", dd: "%d jours", M: "un mois", MM: "%d mois", y: "un an", yy: "%d ans"}, ordinal: function(e3) {
return "" + e3 + (e3 === 1 ? "er" : "e");
return "" + e3 + (e3 === 1 ? "er" : "");
}};
return t2.default.locale(i, null, true), i;
});
@@ -999,7 +999,7 @@ var require_nl = __commonJS((exports, module) => {
return e3 && typeof e3 == "object" && "default" in e3 ? e3 : {default: e3};
}
var d = a2(e2), n2 = {name: "nl", weekdays: "zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"), weekdaysShort: "zo._ma._di._wo._do._vr._za.".split("_"), weekdaysMin: "zo_ma_di_wo_do_vr_za".split("_"), months: "januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"), monthsShort: "jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"), ordinal: function(e3) {
return e3 + (e3 === 1 || e3 === 8 || e3 >= 20 ? "ste" : "de");
return "[" + e3 + (e3 === 1 || e3 === 8 || e3 >= 20 ? "ste" : "de") + "]";
}, weekStart: 1, yearStart: 4, formats: {LT: "HH:mm", LTS: "HH:mm:ss", L: "DD-MM-YYYY", LL: "D MMMM YYYY", LLL: "D MMMM YYYY HH:mm", LLLL: "dddd D MMMM YYYY HH:mm"}, relativeTime: {future: "over %s", past: "%s geleden", s: "een paar seconden", m: "een minuut", mm: "%d minuten", h: "een uur", hh: "%d uur", d: "een dag", dd: "%d dagen", M: "een maand", MM: "%d maanden", y: "een jaar", yy: "%d jaar"}};
return d.default.locale(n2, null, true), n2;
});
@@ -11481,13 +11481,13 @@ var require_choices = __commonJS((exports, module) => {
var _ref3;
var outerSubscribe = subscribe;
return _ref3 = {
subscribe: function subscribe2(observer) {
if (typeof observer !== "object" || observer === null) {
subscribe: function subscribe2(observer2) {
if (typeof observer2 !== "object" || observer2 === null) {
throw new Error(true ? formatProdErrorMessage(11) : 0);
}
function observeState() {
if (observer.next) {
observer.next(getState());
if (observer2.next) {
observer2.next(getState());
}
}
observeState();
@@ -17940,7 +17940,7 @@ var eventPosition = (e2) => ({
scopeTop: e2.offsetY || e2.layerY
});
var createDragNDropClient = (element, scopeToObserve, filterElement) => {
const observer = getDragNDropObserver(scopeToObserve);
const observer2 = getDragNDropObserver(scopeToObserve);
const client = {
element,
filterElement,
@@ -17958,13 +17958,13 @@ var createDragNDropClient = (element, scopeToObserve, filterElement) => {
allowdrop: () => {
}
};
client.destroy = observer.addListener(client);
client.destroy = observer2.addListener(client);
return client;
};
var getDragNDropObserver = (element) => {
const observer = dragNDropObservers.find((item2) => item2.element === element);
if (observer) {
return observer;
const observer2 = dragNDropObservers.find((item2) => item2.element === element);
if (observer2) {
return observer2;
}
const newObserver = createDragNDropObserver(element);
dragNDropObservers.push(newObserver);
@@ -17983,14 +17983,14 @@ var createDragNDropObserver = (element) => {
handlers[event] = createHandler(element, clients);
element.addEventListener(event, handlers[event], false);
});
const observer = {
const observer2 = {
element,
addListener: (client) => {
clients.push(client);
return () => {
clients.splice(clients.indexOf(client), 1);
if (clients.length === 0) {
dragNDropObservers.splice(dragNDropObservers.indexOf(observer), 1);
dragNDropObservers.splice(dragNDropObservers.indexOf(observer2), 1);
forin(routes, (event) => {
element.removeEventListener(event, handlers[event], false);
});
@@ -17998,7 +17998,7 @@ var createDragNDropObserver = (element) => {
};
}
};
return observer;
return observer2;
};
var elementFromPoint = (root2, point) => {
if (!("elementFromPoint" in root2)) {
@@ -24772,7 +24772,7 @@ function applyStyle(button, stylesToApply) {
}
// node_modules/dompurify/dist/purify.es.js
/*! @license DOMPurify 2.3.10 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.10/LICENSE */
/*! @license DOMPurify 2.4.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.0/LICENSE */
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(obj2) {
@@ -25011,7 +25011,7 @@ function createDOMPurify() {
var DOMPurify = function DOMPurify2(root2) {
return createDOMPurify(root2);
};
DOMPurify.version = "2.3.10";
DOMPurify.version = "2.4.0";
DOMPurify.removed = [];
if (!window2 || !window2.document || window2.document.nodeType !== 9) {
DOMPurify.isSupported = false;
@@ -25081,6 +25081,8 @@ function createDOMPurify() {
var RETURN_DOM_FRAGMENT = false;
var RETURN_TRUSTED_TYPE = false;
var SANITIZE_DOM = true;
var SANITIZE_NAMED_PROPS = false;
var SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
var KEEP_CONTENT = true;
var IN_PLACE = false;
var USE_PROFILES = {};
@@ -25134,6 +25136,7 @@ function createDOMPurify() {
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
FORCE_BODY = cfg.FORCE_BODY || false;
SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
IN_PLACE = cfg.IN_PLACE || false;
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
@@ -25497,6 +25500,10 @@ function createDOMPurify() {
if (!_isValidAttribute(lcTag, lcName, value)) {
continue;
}
if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name")) {
_removeAttribute(name2, currentNode);
value = SANITIZE_NAMED_PROPS_PREFIX + value;
}
if (trustedTypesPolicy && _typeof(trustedTypes) === "object" && typeof trustedTypes.getAttributeType === "function") {
if (namespaceURI)
;
@@ -25539,7 +25546,8 @@ function createDOMPurify() {
}
_executeHook("afterSanitizeShadowDOM", fragment, null);
};
DOMPurify.sanitize = function(dirty, cfg) {
DOMPurify.sanitize = function(dirty) {
var cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
var body;
var importedNode;
var currentNode;
@@ -25691,6 +25699,7 @@ var purify = createDOMPurify();
// node_modules/marked/lib/marked.esm.js
function getDefaults() {
return {
async: false,
baseUrl: null,
breaks: false,
extensions: null,
@@ -25933,7 +25942,7 @@ function outputLink(cap, link, raw, lexer2) {
href,
title,
text: text3,
tokens: lexer2.inlineTokens(text3, [])
tokens: lexer2.inlineTokens(text3)
};
lexer2.state.inLink = false;
return token;
@@ -26014,15 +26023,13 @@ var Tokenizer = class {
text3 = trimmed.trim();
}
}
const token = {
return {
type: "heading",
raw: cap[0],
depth: cap[1].length,
text: text3,
tokens: []
tokens: this.lexer.inline(text3)
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
hr(src) {
@@ -26192,10 +26199,10 @@ var Tokenizer = class {
text: cap[0]
};
if (this.options.sanitize) {
const text3 = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
token.type = "paragraph";
token.text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
token.tokens = [];
this.lexer.inline(token.text, token.tokens);
token.text = text3;
token.tokens = this.lexer.inline(text3);
}
return token;
}
@@ -26249,15 +26256,13 @@ var Tokenizer = class {
}
l = item2.header.length;
for (j = 0; j < l; j++) {
item2.header[j].tokens = [];
this.lexer.inline(item2.header[j].text, item2.header[j].tokens);
item2.header[j].tokens = this.lexer.inline(item2.header[j].text);
}
l = item2.rows.length;
for (j = 0; j < l; j++) {
row = item2.rows[j];
for (k = 0; k < row.length; k++) {
row[k].tokens = [];
this.lexer.inline(row[k].text, row[k].tokens);
row[k].tokens = this.lexer.inline(row[k].text);
}
}
return item2;
@@ -26267,41 +26272,36 @@ var Tokenizer = class {
lheading(src) {
const cap = this.rules.block.lheading.exec(src);
if (cap) {
const token = {
return {
type: "heading",
raw: cap[0],
depth: cap[2].charAt(0) === "=" ? 1 : 2,
text: cap[1],
tokens: []
tokens: this.lexer.inline(cap[1])
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
paragraph(src) {
const cap = this.rules.block.paragraph.exec(src);
if (cap) {
const token = {
const text3 = cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1];
return {
type: "paragraph",
raw: cap[0],
text: cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1],
tokens: []
text: text3,
tokens: this.lexer.inline(text3)
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
text(src) {
const cap = this.rules.block.text.exec(src);
if (cap) {
const token = {
return {
type: "text",
raw: cap[0],
text: cap[0],
tokens: []
tokens: this.lexer.inline(cap[0])
};
this.lexer.inline(token.text, token.tokens);
return token;
}
}
escape(src) {
@@ -26436,7 +26436,7 @@ var Tokenizer = class {
type: "em",
raw: src.slice(0, lLength + match.index + rLength + 1),
text: text4,
tokens: this.lexer.inlineTokens(text4, [])
tokens: this.lexer.inlineTokens(text4)
};
}
const text3 = src.slice(2, lLength + match.index + rLength - 1);
@@ -26444,7 +26444,7 @@ var Tokenizer = class {
type: "strong",
raw: src.slice(0, lLength + match.index + rLength + 1),
text: text3,
tokens: this.lexer.inlineTokens(text3, [])
tokens: this.lexer.inlineTokens(text3)
};
}
}
@@ -26482,7 +26482,7 @@ var Tokenizer = class {
type: "del",
raw: cap[0],
text: cap[2],
tokens: this.lexer.inlineTokens(cap[2], [])
tokens: this.lexer.inlineTokens(cap[2])
};
}
}
@@ -26895,8 +26895,9 @@ var Lexer = class {
this.state.top = true;
return tokens;
}
inline(src, tokens) {
inline(src, tokens = []) {
this.inlineQueue.push({src, tokens});
return tokens;
}
inlineTokens(src, tokens = []) {
let token, lastToken, cutSrc;
@@ -27482,19 +27483,27 @@ function marked(src, opt, callback) {
}
return;
}
try {
const tokens = Lexer.lex(src, opt);
if (opt.walkTokens) {
marked.walkTokens(tokens, opt.walkTokens);
}
return Parser.parse(tokens, opt);
} catch (e2) {
function onError(e2) {
e2.message += "\nPlease report this to https://github.com/markedjs/marked.";
if (opt.silent) {
return "<p>An error occurred:</p><pre>" + escape(e2.message + "", true) + "</pre>";
}
throw e2;
}
try {
const tokens = Lexer.lex(src, opt);
if (opt.walkTokens) {
if (opt.async) {
return Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => {
return Parser.parse(tokens, opt);
}).catch(onError);
}
marked.walkTokens(tokens, opt.walkTokens);
}
return Parser.parse(tokens, opt);
} catch (e2) {
onError(e2);
}
}
marked.options = marked.setOptions = function(opt) {
merge(marked.defaults, opt);
@@ -27589,10 +27598,12 @@ marked.use = function(...args) {
if (pack.walkTokens) {
const walkTokens2 = marked.defaults.walkTokens;
opts.walkTokens = function(token) {
pack.walkTokens.call(this, token);
let values = [];
values.push(pack.walkTokens.call(this, token));
if (walkTokens2) {
walkTokens2.call(this, token);
values = values.concat(walkTokens2.call(this, token));
}
return values;
};
}
if (hasExtensions) {
@@ -27602,35 +27613,37 @@ marked.use = function(...args) {
});
};
marked.walkTokens = function(tokens, callback) {
let values = [];
for (const token of tokens) {
callback.call(marked, token);
values = values.concat(callback.call(marked, token));
switch (token.type) {
case "table": {
for (const cell of token.header) {
marked.walkTokens(cell.tokens, callback);
values = values.concat(marked.walkTokens(cell.tokens, callback));
}
for (const row of token.rows) {
for (const cell of row) {
marked.walkTokens(cell.tokens, callback);
values = values.concat(marked.walkTokens(cell.tokens, callback));
}
}
break;
}
case "list": {
marked.walkTokens(token.items, callback);
values = values.concat(marked.walkTokens(token.items, callback));
break;
}
default: {
if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) {
marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
marked.walkTokens(token[childTokens], callback);
values = values.concat(marked.walkTokens(token[childTokens], callback));
});
} else if (token.tokens) {
marked.walkTokens(token.tokens, callback);
values = values.concat(marked.walkTokens(token.tokens, callback));
}
}
}
}
return values;
};
marked.parseInline = function(src, opt) {
if (typeof src === "undefined" || src === null) {
@@ -34746,11 +34759,11 @@ function autoUpdate(reference, floating, update, options2) {
});
ancestorResize && ancestor.addEventListener("resize", update);
});
let observer = null;
let observer2 = null;
if (elementResize) {
observer = new ResizeObserver(update);
isElement(reference) && observer.observe(reference);
observer.observe(floating);
observer2 = new ResizeObserver(update);
isElement(reference) && observer2.observe(reference);
observer2.observe(floating);
}
let frameId;
let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
@@ -34775,8 +34788,8 @@ function autoUpdate(reference, floating, update, options2) {
ancestorScroll && ancestor.removeEventListener("scroll", update);
ancestorResize && ancestor.removeEventListener("resize", update);
});
(_observer = observer) == null ? void 0 : _observer.disconnect();
observer = null;
(_observer = observer2) == null ? void 0 : _observer.disconnect();
observer2 = null;
if (animationFrame) {
cancelAnimationFrame(frameId);
}
@@ -34878,6 +34891,147 @@ var randomString = (length) => {
}
return str;
};
var onAttributeAddeds = [];
var onElRemoveds = [];
var onElAddeds = [];
function cleanupAttributes(el, names) {
if (!el._x_attributeCleanups)
return;
Object.entries(el._x_attributeCleanups).forEach(([name2, value]) => {
if (names === void 0 || names.includes(name2)) {
value.forEach((i) => i());
delete el._x_attributeCleanups[name2];
}
});
}
var observer = new MutationObserver(onMutate);
var currentlyObserving = false;
function startObservingMutations() {
observer.observe(document, {subtree: true, childList: true, attributes: true, attributeOldValue: true});
currentlyObserving = true;
}
function stopObservingMutations() {
flushObserver();
observer.disconnect();
currentlyObserving = false;
}
var recordQueue = [];
var willProcessRecordQueue = false;
function flushObserver() {
recordQueue = recordQueue.concat(observer.takeRecords());
if (recordQueue.length && !willProcessRecordQueue) {
willProcessRecordQueue = true;
queueMicrotask(() => {
processRecordQueue();
willProcessRecordQueue = false;
});
}
}
function processRecordQueue() {
onMutate(recordQueue);
recordQueue.length = 0;
}
function mutateDom(callback) {
if (!currentlyObserving)
return callback();
stopObservingMutations();
let result = callback();
startObservingMutations();
return result;
}
var isCollecting = false;
var deferredMutations = [];
function onMutate(mutations) {
if (isCollecting) {
deferredMutations = deferredMutations.concat(mutations);
return;
}
let addedNodes = [];
let removedNodes = [];
let addedAttributes = /* @__PURE__ */ new Map();
let removedAttributes = /* @__PURE__ */ new Map();
for (let i = 0; i < mutations.length; i++) {
if (mutations[i].target._x_ignoreMutationObserver)
continue;
if (mutations[i].type === "childList") {
mutations[i].addedNodes.forEach((node) => node.nodeType === 1 && addedNodes.push(node));
mutations[i].removedNodes.forEach((node) => node.nodeType === 1 && removedNodes.push(node));
}
if (mutations[i].type === "attributes") {
let el = mutations[i].target;
let name2 = mutations[i].attributeName;
let oldValue = mutations[i].oldValue;
let add = () => {
if (!addedAttributes.has(el))
addedAttributes.set(el, []);
addedAttributes.get(el).push({name: name2, value: el.getAttribute(name2)});
};
let remove = () => {
if (!removedAttributes.has(el))
removedAttributes.set(el, []);
removedAttributes.get(el).push(name2);
};
if (el.hasAttribute(name2) && oldValue === null) {
add();
} else if (el.hasAttribute(name2)) {
remove();
add();
} else {
remove();
}
}
}
removedAttributes.forEach((attrs, el) => {
cleanupAttributes(el, attrs);
});
addedAttributes.forEach((attrs, el) => {
onAttributeAddeds.forEach((i) => i(el, attrs));
});
for (let node of removedNodes) {
if (addedNodes.includes(node))
continue;
onElRemoveds.forEach((i) => i(node));
if (node._x_cleanups) {
while (node._x_cleanups.length)
node._x_cleanups.pop()();
}
}
addedNodes.forEach((node) => {
node._x_ignoreSelf = true;
node._x_ignore = true;
});
for (let node of addedNodes) {
if (removedNodes.includes(node))
continue;
if (!node.isConnected)
continue;
delete node._x_ignoreSelf;
delete node._x_ignore;
onElAddeds.forEach((i) => i(node));
node._x_ignore = true;
node._x_ignoreSelf = true;
}
addedNodes.forEach((node) => {
delete node._x_ignoreSelf;
delete node._x_ignore;
});
addedNodes = null;
removedNodes = null;
addedAttributes = null;
removedAttributes = null;
}
function once(callback, fallback = () => {
}) {
let called = false;
return function() {
if (!called) {
called = true;
callback.apply(this, arguments);
} else {
fallback.apply(this, arguments);
}
};
}
function src_default(Alpine) {
const defaultOptions2 = {
dismissable: true,
@@ -34980,7 +35134,7 @@ function src_default(Alpine) {
togglePanel();
};
});
Alpine.directive("float", (panel2, {modifiers, expression}, {evaluate}) => {
Alpine.directive("float", (panel2, {modifiers, expression}, {evaluate, effect}) => {
const settings = expression ? evaluate(expression) : {};
const config = modifiers.length > 0 ? buildDirectiveConfigFromModifiers(modifiers, settings) : {};
let cleanup = null;
@@ -34993,13 +35147,52 @@ function src_default(Alpine) {
const component = panel2.parentElement.closest("[x-data]");
const atTrigger = component.querySelectorAll(`[\\@click^="$refs.${refName}"]`);
const xTrigger = component.querySelectorAll(`[x-on\\:click^="$refs.${refName}"]`);
panel2.style.setProperty("display", "none");
setupA11y(component, [...atTrigger, ...xTrigger][0], panel2);
panel2.isOpen = false;
panel2._x_isShown = false;
panel2.trigger = null;
if (!panel2._x_doHide)
panel2._x_doHide = () => {
mutateDom(() => {
panel2.style.setProperty("display", "none", modifiers.includes("important") ? "important" : void 0);
});
};
if (!panel2._x_doShow)
panel2._x_doShow = () => {
mutateDom(() => {
panel2.style.setProperty("display", "block", modifiers.includes("important") ? "important" : void 0);
});
};
let hide2 = () => {
panel2._x_doHide();
panel2._x_isShown = false;
};
let show = () => {
panel2._x_doShow();
panel2._x_isShown = true;
};
let clickAwayCompatibleShow = () => setTimeout(show);
let toggle = once((value) => value ? show() : hide2(), (value) => {
if (typeof panel2._x_toggleAndCascadeWithTransitions === "function") {
panel2._x_toggleAndCascadeWithTransitions(panel2, value, show, hide2);
} else {
value ? clickAwayCompatibleShow() : hide2();
}
});
let oldValue;
let firstTime = true;
effect(() => evaluate((value) => {
if (!firstTime && value === oldValue)
return;
if (modifiers.includes("immediate"))
value ? clickAwayCompatibleShow() : hide2();
toggle(value);
oldValue = value;
firstTime = false;
}));
panel2.open = async function(event) {
panel2.trigger = event.currentTarget ? event.currentTarget : event;
panel2.isOpen = true;
panel2.style.display = "block";
toggle(true);
panel2.trigger.setAttribute("aria-expanded", true);
if (config.component.trap)
panel2.setAttribute("x-trap", true);
@@ -35039,8 +35232,7 @@ function src_default(Alpine) {
window.addEventListener("keydown", keyEscape, true);
};
panel2.close = function() {
panel2.isOpen = false;
panel2.style.display = "";
toggle(false);
panel2.trigger.setAttribute("aria-expanded", false);
if (config.component.trap)
panel2.setAttribute("x-trap", false);
@@ -35049,7 +35241,7 @@ function src_default(Alpine) {
window.removeEventListener("keydown", keyEscape, false);
};
panel2.toggle = function(event) {
panel2.isOpen ? panel2.close() : panel2.open(event);
panel2._x_isShown ? panel2.close() : panel2.open(event);
};
});
}
+89
View File
@@ -0,0 +1,89 @@
---
title: Testing
---
All examples in this guide will be written using [Pest](https://pestphp.com). However, you can easily adapt this to a PHPUnit.
Since the form builder works on Livewire components, you can use the [Livewire testing helpers](https://laravel-livewire.com/docs/testing). However, we have custom testing helpers that you can use with forms:
## Form existance
To check that a Livewire component has a form, use `assertFormExists()`:
```php
use function Pest\Livewire\livewire;
it('has a form', function () {
livewire(CreatePost::class)
->assertFormExists();
});
```
> Note that if you have multiple forms on a Livewire component, you can pass the name of a specific form like `assertFormExists('createPostForm')`.
## Fields
To ensure that a form has a given field pass the field name to `assertFormFieldExists()`:
```php
use function Pest\Livewire\livewire;
it('has a title field', function () {
livewire(CreatePost::class)
->assertFormFieldExists('title');
});
```
> Note that if you have multiple forms on a Livewire component, you can specify which form you want to check for the existence of the field like `assertFormFieldExists('title', 'createPostForm')`.
### Hidden fields
To ensure that a field is visible pass the name to `assertFormFieldIsVisible()`:
```php
use function Pest\Livewire\livewire;
test('title is visible', function () {
livewire(CreatePost::class)
->assertFormFieldIsVisible('title');
});
```
Or to ensure that a field is hidden you can pass the name to `assertFormFieldIsHidden()`:
```php
use function Pest\Livewire\livewire;
test('title is hidden', function () {
livewire(CreatePost::class)
->assertFormFieldIsHidden('title');
});
```
> Note that for both `assertFormFieldIsHidden()` and `assertFormFieldIsVisible()` you can pass the name of a specific form the field belongs to as the second argument like `assertFormFieldIsHidden('title', 'createPostForm')`.
### Disabled fields
To ensure that a field is enabled pass the name to `assertFormFieldIsEnabled()`:
```php
use function Pest\Livewire\livewire;
test('title is enabled', function () {
livewire(CreatePost::class)
->assertFormFieldIsEnabled('title');
});
```
Or to ensure that a field is disabled you can pass the name to `assertFormFieldIsDisabled()`:
```php
use function Pest\Livewire\livewire;
test('title is disabled', function () {
livewire(CreatePost::class)
->assertFormFieldIsDisabled('title');
});
```
> Note that for both `assertFormFieldIsEnabled()` and `assertFormFieldIsDisabled()` you can pass the name of a specific form the field belongs to as the second argument like `assertFormFieldIsEnabled('title', 'createPostForm')`.
@@ -4,16 +4,14 @@ return [
'builder' => [
'collapsed' => 'Conteúdo recolhido',
'buttons' => [
'create_item' => [
'label' => 'Adicionar em :label',
],
'create_item_between' => [
'label' => 'Adicionar entre',
],
'delete_item' => [
'label' => 'Excluír',
],
@@ -26,6 +24,22 @@ return [
'label' => 'Mover para cima',
],
'collapse_item' => [
'label' => 'Recolher',
],
'expand_item' => [
'label' => 'Expandir',
],
'collapse_all' => [
'label' => 'Recolher todos',
],
'expand_all' => [
'label' => 'Expandir todos',
],
],
],
@@ -77,6 +91,8 @@ return [
'repeater' => [
'collapsed' => 'Conteúdo recolhido',
'buttons' => [
'create_item' => [
@@ -87,6 +103,10 @@ return [
'label' => 'Excluír',
],
'clone_item' => [
'label' => 'Clonar',
],
'move_item_down' => [
'label' => 'Mover para baixo',
],
@@ -95,6 +115,14 @@ return [
'label' => 'Mover para cima',
],
'collapse_item' => [
'label' => 'Recolher',
],
'expand_item' => [
'label' => 'Expandir',
],
'collapse_all' => [
'label' => 'Recolher todos',
],
@@ -146,8 +174,42 @@ return [
],
'select' => [
'actions' => [
'create_option' => [
'modal' => [
'heading' => 'Criar',
'actions' => [
'create' => [
'label' => 'Criar',
],
],
],
],
],
'boolean' => [
'true' => 'Sim',
'false' => 'Não',
],
'loading_message' => 'Carregando...',
'no_search_results_message' => 'Nenhuma opção corresponde à sua pesquisa.',
'placeholder' => 'Selecione uma opção',
'searching_message' => 'Buscando...',
'search_prompt' => 'Comece a digitar para pesquisar...',
],
@@ -155,4 +217,20 @@ return [
'placeholder' => 'Novo rótulo',
],
'wizard' => [
'buttons' => [
'previous_step' => [
'label' => 'Voltar',
],
'next_step' => [
'label' => 'Próximo',
],
],
],
];
@@ -103,6 +103,10 @@ return [
'label' => 'Удалить',
],
'clone_item' => [
'label' => 'Клонировать',
],
'move_item_down' => [
'label' => 'Переместить вниз',
],
@@ -192,6 +196,12 @@ return [
],
],
'boolean' => [
'true' => 'Да',
'false' => 'Нет',
],
'loading_message' => 'Загрузка...',
'no_search_results_message' => 'Нет вариантов, соответствующих вашему запросу.',
+31 -23
View File
@@ -4,7 +4,7 @@ return [
'builder' => [
'collapsed' => 'Вміст згорнуто',
'collapsed' => 'Вміст згорнутий',
'buttons' => [
@@ -77,21 +77,21 @@ return [
'toolbar_buttons' => [
'attach_files' => 'Прикріпити файли',
'bold' => 'Жирний',
'bullet_list' => 'Пунктовий список',
'code_block' => 'Блок коду',
'edit' => 'Змінити',
'italic' => 'Курсив',
'bullet_list' => 'Маркувальний список',
'code_block' => 'Код',
'edit' => 'Редагувати',
'italic' => 'Курсів',
'link' => 'Посилання',
'ordered_list' => 'Нумерований список',
'preview' => опередній перегляд',
'strike' => 'Закреслення',
'preview' => 'Перегляд',
'strike' => 'Закреслений',
],
],
'repeater' => [
'collapsed' => 'Вміст згорнуто',
'collapsed' => 'Вміст згорнутий',
'buttons' => [
@@ -103,6 +103,10 @@ return [
'label' => 'Видалити',
],
'clone_item' => [
'label' => 'Клонувати',
],
'move_item_down' => [
'label' => 'Перемістити вниз',
],
@@ -138,13 +142,13 @@ return [
'link' => [
'buttons' => [
'link' => 'Додати посилання',
'unlink' => 'Видалити посилання',
'link' => 'Посилання',
'unlink' => 'Прибрати посилання',
],
'label' => 'URL',
'placeholder' => 'Введіть URL-адресу',
'placeholder' => 'Введіть URL',
],
@@ -152,19 +156,19 @@ return [
'toolbar_buttons' => [
'attach_files' => 'Прикріпити файли',
'blockquote' => 'Блок-цитата',
'blockquote' => 'Цитата',
'bold' => 'Жирний',
'bullet_list' => 'Пунктовий список',
'code_block' => 'Блок коду',
'h1' => 'Тайтл',
'h2' => 'Заголовок',
'h3' => 'Підзаголовок',
'italic' => 'Курсив',
'bullet_list' => 'Маркувальний список',
'code_block' => 'Код',
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'italic' => 'Курсів',
'link' => 'Посилання',
'ordered_list' => 'Нумерований список',
'redo' => 'Повторити',
'strike' => 'Закреслення',
'undo' => 'Відмінити',
'strike' => 'Закреслений',
'undo' => 'Скасувати',
],
],
@@ -193,16 +197,20 @@ return [
],
'boolean' => [
'true' => 'Так',
'false' => 'Ні',
],
'loading_message' => 'Завантаження...',
'no_search_results_message' => 'Жоден варіант не відповідає вашому пошуку.',
'no_search_results_message' => 'Немає варіантів, які відповідають вашому запиту.',
'placeholder' => 'Виберіть варіант',
'searching_message' => 'Пошук...',
'search_prompt' => 'Почніть вводити для пошуку...',
'search_prompt' => 'Введіть текст для пошуку...',
],
'tags_input' => [
@@ -189,21 +189,20 @@
x-transition
class="absolute inset-x-0 bottom-0 z-10 flex items-center justify-center h-12 -mb-12"
>
<div x-data class="relative flex justify-center">
<x-forms::icon-button
:label="$getCreateItemBetweenButtonLabel()"
icon="heroicon-o-plus"
x-on:click="$refs.panel.toggle"
type="button"
/>
<x-forms::dropdown>
<x-slot name="trigger">
<x-forms::icon-button
:label="$getCreateItemBetweenButtonLabel()"
icon="heroicon-o-plus"
/>
</x-slot>
<x-forms::builder.block-picker
:blocks="$getBlocks()"
:create-after-item="$uuid"
:state-path="$getStatePath()"
class="py-2"
/>
</div>
</x-forms::dropdown>
</div>
@endif
</li>
@@ -212,20 +211,18 @@
@endif
@if (! $isItemCreationDisabled)
<div x-data class="relative flex justify-center">
<x-forms::button
size="sm"
x-on:click="$refs.panel.toggle"
type="button"
>
{{ $getCreateItemButtonLabel() }}
</x-forms::button>
<x-forms::dropdown class="flex justify-center">
<x-slot name="trigger">
<x-forms::button size="sm">
{{ $getCreateItemButtonLabel() }}
</x-forms::button>
</x-slot>
<x-forms::builder.block-picker
:blocks="$getBlocks()"
:state-path="$getStatePath()"
/>
</div>
</x-forms::dropdown>
@endif
</div>
</x-dynamic-component>
@@ -4,24 +4,14 @@
'statePath',
])
<div
x-ref="panel"
x-transition
x-cloak
x-float.placement.bottom.flip.offset="{ offset: 8 }"
{{ $attributes->class(['filament-forms-builder-component-block-picker absolute hidden z-20 w-52']) }}
>
<ul @class([
'py-1 space-y-1 bg-white shadow rounded-xl shadow-xl ring-1 ring-gray-900/10 overflow-hidden rounded-xl',
'dark:bg-gray-700 dark:divide-gray-600 dark:ring-white/20' => config('forms.dark_mode'),
])>
@foreach ($blocks as $block)
<x-forms::dropdown.item
:wire:click="'dispatchFormEvent(\'builder::createItem\', \'' . $statePath . '\', \'' . $block->getName() . '\'' . ($createAfterItem ? ', \'' . $createAfterItem . '\'' : '') . ')'"
:icon="$block->getIcon()"
>
{{ $block->getLabel() }}
</x-forms::dropdown.item>
@endforeach
</ul>
<div {{ $attributes->class(['filament-forms-builder-component-block-picker']) }}>
@foreach ($blocks as $block)
<x-forms::dropdown.item
:wire:click="'dispatchFormEvent(\'builder::createItem\', \'' . $statePath . '\', \'' . $block->getName() . '\'' . ($createAfterItem ? ', \'' . $createAfterItem . '\'' : '') . ')'"
:icon="$block->getIcon()"
x-on:click="close"
>
{{ $block->getLabel() }}
</x-forms::dropdown.item>
@endforeach
</div>
@@ -0,0 +1,10 @@
@captureSlots([
'trigger',
])
<x-filament-support::dropdown
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->merge($slots)"
:dark-mode="config('forms.dark_mode')"
>
{{ $slot }}
</x-filament-support::dropdown>
@@ -54,7 +54,7 @@
x-on:click="tab = '{{ $tab->getId() }}'"
role="tab"
x-bind:tabindex="tab === '{{ $tab->getId() }}' ? 0 : -1"
class="flex items-center gap-2 shrink-0 p-3 text-sm font-medium"
class="filament-forms-tabs-component-button flex items-center gap-2 shrink-0 p-3 text-sm font-medium"
x-bind:class="{
'text-gray-500 @if (config('forms.dark_mode')) dark:text-gray-400 @endif': tab !== '{{ $tab->getId() }}',
'bg-white text-primary-600 @if (config('forms.dark_mode')) dark:bg-gray-800 @endif': tab === '{{ $tab->getId() }}',
+5 -1
View File
@@ -36,10 +36,14 @@ class Field extends Component implements Contracts\HasValidationRules
public function getLabel(): string | Htmlable | null
{
return parent::getLabel() ?? (string) Str::of($this->getName())
$label = parent::getLabel() ?? (string) Str::of($this->getName())
->afterLast('.')
->kebab()
->replace(['-', '_'], ' ')
->ucfirst();
return is_string($label) && $this->shouldTranslateLabel
? __($label)
: $label;
}
}
@@ -75,6 +75,12 @@ trait CanBeValidated
return [];
}
return $this->getLivewire()->validate($this->getValidationRules(), [], $this->getValidationAttributes());
$rules = $this->getValidationRules();
if (! count($rules)) {
return [];
}
return $this->getLivewire()->validate($rules, [], $this->getValidationAttributes());
}
}
@@ -2,6 +2,8 @@
namespace Filament\Forms;
use Filament\Forms\Testing\TestsForms;
use Livewire\Testing\TestableLivewire;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
@@ -39,4 +41,9 @@ class FormsServiceProvider extends PackageServiceProvider
return array_merge($commands, $aliases);
}
public function packageBooted(): void
{
TestableLivewire::mixin(new TestsForms());
}
}
+158
View File
@@ -0,0 +1,158 @@
<?php
namespace Filament\Forms\Testing;
use Closure;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Field;
use Filament\Forms\Contracts\HasForms;
use Illuminate\Testing\Assert;
use Livewire\Testing\TestableLivewire;
/**
* @method HasForms instance()
*
* @mixin TestableLivewire
*/
class TestsForms
{
public function assertFormExists(): Closure
{
return function (string $name = 'form'): static {
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$name;
Assert::assertInstanceOf(
ComponentContainer::class,
$form,
"Failed asserting that a form with the name [{$name}] exists on the [{$livewireClass}] component."
);
return $this;
};
}
public function assertFormFieldExists(): Closure
{
return function (string $fieldName, string $formName = 'form'): static {
/** @phpstan-ignore-next-line */
$this->assertFormExists($formName);
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$formName;
/** @var ?Field $field */
$field = data_get($form->getFlatFields(withHidden: true), $fieldName, null);
Assert::assertInstanceOf(
Field::class,
$field,
"Failed asserting that a field with the name [{$fieldName}] exists on the form with the name [${formName}] on the [{$livewireClass}] component."
);
return $this;
};
}
public function assertFormFieldIsDisabled(): Closure
{
return function (string $fieldName, string $formName = 'form'): static {
/** @phpstan-ignore-next-line */
$this->assertFormFieldExists($fieldName, $formName);
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$formName;
/** @var Field $field */
$field = $form->getFlatFields(withHidden: true)[$fieldName];
Assert::assertTrue(
$field->isDisabled(),
"Failed asserting that a field with the name [{$fieldName}] is disabled on the form named [{$formName}] on the [{$livewireClass}] component."
);
return $this;
};
}
public function assertFormFieldIsEnabled(): Closure
{
return function (string $fieldName, string $formName = 'form'): static {
/** @phpstan-ignore-next-line */
$this->assertFormFieldExists($fieldName, $formName);
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$formName;
/** @var Field $field */
$field = $form->getFlatFields(withHidden: true)[$fieldName];
Assert::assertFalse(
$field->isDisabled(),
"Failed asserting that a field with the name [{$fieldName}] is enabled on the form named [{$formName}] on the [{$livewireClass}] component."
);
return $this;
};
}
public function assertFormFieldIsHidden(): Closure
{
return function (string $fieldName, string $formName = 'form'): static {
/** @phpstan-ignore-next-line */
$this->assertFormFieldExists($fieldName, $formName);
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$formName;
$fields = $form->getFlatFields(withHidden: false);
Assert::assertArrayNotHasKey(
$fieldName,
$fields,
"Failed asserting that a field with the name [{$fieldName}] is hidden on the form named [{$formName}] on the [{$livewireClass}] component."
);
return $this;
};
}
public function assertFormFieldIsVisible(): Closure
{
return function (string $fieldName, string $formName = 'form'): static {
/** @phpstan-ignore-next-line */
$this->assertFormFieldExists($fieldName, $formName);
$livewire = $this->instance();
$livewireClass = $livewire::class;
/** @var ComponentContainer $form */
$form = $livewire->$formName;
$fields = $form->getFlatFields(withHidden: false);
Assert::assertArrayHasKey(
$fieldName,
$fields,
"Failed asserting that a field with the name [{$fieldName}] is visible on the form named [{$formName}] on the [{$livewireClass}] component."
);
return $this;
};
}
}
@@ -0,0 +1,9 @@
<?php
return [
'active_locale' => [
'label' => 'Idioma',
],
];
@@ -0,0 +1,41 @@
<?php
return [
'single' => [
'label' => 'Associar',
'modal' => [
'heading' => 'Associar :label',
'fields' => [
'record_id' => [
'label' => 'Registro',
],
],
'actions' => [
'associate' => [
'label' => 'Associar',
],
'associate_another' => [
'label' => 'Associar e Associar outro',
],
],
],
'messages' => [
'associated' => 'Associado',
],
],
];
@@ -0,0 +1,53 @@
<?php
return [
'single' => [
'label' => 'Dissociar',
'modal' => [
'heading' => 'Dissociar :label',
'actions' => [
'dissociate' => [
'label' => 'Dissociar',
],
],
],
'messages' => [
'dissociated' => 'Dissociado',
],
],
'multiple' => [
'label' => 'Dissociar selecionado',
'modal' => [
'heading' => 'Dissociar selecionado :label',
'actions' => [
'dissociate' => [
'label' => 'Dissociar',
],
],
],
'messages' => [
'dissociated' => 'Dissociado',
],
],
];
@@ -0,0 +1,53 @@
<?php
return [
'single' => [
'label' => 'Forçar exclusão',
'modal' => [
'heading' => 'Forçar exclusão de :label',
'actions' => [
'delete' => [
'label' => 'Excluir',
],
],
],
'messages' => [
'deleted' => 'Excluido',
],
],
'multiple' => [
'label' => 'Forçar exclusão selecionado',
'modal' => [
'heading' => 'Forçar exclusão selecionado :label',
'actions' => [
'delete' => [
'label' => 'Excluir selecionado',
],
],
],
'messages' => [
'deleted' => 'Excluido',
],
],
];
@@ -0,0 +1,29 @@
<?php
return [
'single' => [
'label' => 'Replicar',
'modal' => [
'heading' => 'Replicar :label',
'actions' => [
'replicate' => [
'label' => 'Replicar',
],
],
],
'messages' => [
'replicated' => 'Replicado',
],
],
];
@@ -0,0 +1,53 @@
<?php
return [
'single' => [
'label' => 'Restaurar',
'modal' => [
'heading' => 'Restaurar :label',
'actions' => [
'restore' => [
'label' => 'Restaurar',
],
],
],
'messages' => [
'restored' => 'Restaurado',
],
],
'multiple' => [
'label' => 'Restaurar selecionado',
'modal' => [
'heading' => 'Restaurar selecionado :label',
'actions' => [
'restore' => [
'label' => 'Restaurar',
],
],
],
'messages' => [
'restored' => 'Restored',
],
],
];
@@ -0,0 +1,25 @@
<?php
return [
'single' => [
'label' => 'Visualizar',
'modal' => [
'heading' => 'Visualizar :label',
'actions' => [
'close' => [
'label' => 'Fechar',
],
],
],
],
];
@@ -0,0 +1,9 @@
<?php
return [
'messages' => [
'uploading_file' => 'Enviando arquivo...',
],
];
@@ -7,39 +7,28 @@
'tooltip' => null,
])
<div x-data {{ $attributes->class(['relative']) }}>
<x-filament-support::icon-button
x-on:click="$refs.panel.toggle"
:color="$color"
:dark-mode="$darkMode"
:icon="$icon"
:tooltip="$tooltip"
class="-my-2"
>
<x-slot name="label">
{{ $label }}
</x-slot>
</x-filament-support::icon-button>
<x-filament-support::dropdown
:dark-mode="$darkMode"
placement="bottom-end"
teleport
{{ $attributes }}
>
<x-slot name="trigger">
<x-filament-support::icon-button
:color="$color"
:dark-mode="$darkMode"
:icon="$icon"
:tooltip="$tooltip"
>
<x-slot name="label">
{{ $label }}
</x-slot>
</x-filament-support::icon-button>
</x-slot>
<div
x-ref="panel"
x-transition
x-cloak
x-float.placement.bottom-end.flip.offset.shift.teleport="{ offset: 8 }"
@class([
'filament-action-group-dropdown absolute hidden z-20 shadow-xl ring-1 ring-gray-900/10 overflow-hidden rounded-xl w-52',
'dark:ring-white/20' => $darkMode,
])
>
<ul @class([
'py-1 space-y-1 bg-white shadow rounded-xl',
'dark:bg-gray-700 dark:divide-gray-600' => $darkMode,
])>
@foreach ($actions as $action)
@if (! $action->isHidden())
{{ $action }}
@endif
@endforeach
</ul>
</div>
</div>
@foreach ($actions as $action)
@if (! $action->isHidden())
{{ $action }}
@endif
@endforeach
</x-filament-support::dropdown>
@@ -0,0 +1,62 @@
@props([
'darkMode' => false,
'placement' => null,
'shift' => false,
'teleport' => false,
'trigger' => null,
'width' => null,
])
<div
{{ $attributes->class(['filament-dropdown']) }}
x-data="{
toggle: function (event) {
$refs.panel.toggle(event)
},
open: function (event) {
$refs.panel.open(event)
},
close: function (event) {
$refs.panel.close(event)
},
}"
>
<div
class="filament-dropdown-trigger cursor-pointer"
x-on:click="toggle"
>
{{ $trigger }}
</div>
<div
x-ref="panel"
x-float{{ $placement ? ".placement.{$placement}" : '' }}.flip.offset{{ $shift ? '.shift' : '' }}{{ $teleport ? '.teleport' : '' }}="{ offset: 8 }"
x-cloak
x-transition:enter-start="opacity-0 scale-95"
x-transition:leave-end="opacity-0 scale-95"
@if ($attributes->has('wire:key'))
wire:ignore.self
wire:key="{{ $attributes->get('wire:key') }}.panel"
@endif
@class([
'filament-dropdown-panel absolute z-10 w-full rounded-lg bg-white shadow-lg ring-1 ring-black/5 transition',
'dark:bg-gray-800 dark:ring-white/10' => $darkMode,
match ($width) {
'xs' => 'max-w-xs',
'sm' => 'max-w-sm',
'md' => 'max-w-md',
'lg' => 'max-w-lg',
'xl' => 'max-w-xl',
'2xl' => 'max-w-2xl',
'3xl' => 'max-w-3xl',
'4xl' => 'max-w-4xl',
'5xl' => 'max-w-5xl',
'6xl' => 'max-w-6xl',
'7xl' => 'max-w-7xl',
default => 'max-w-[14rem]',
},
])
>
{{ $slot }}
</div>
</div>
@@ -41,7 +41,7 @@
]);
@endphp
<li {{ $attributes->only(['class']) }}>
<div {{ $attributes->only(['class']) }}>
@if ($tag === 'button')
<button
type="{{ $type }}"
@@ -101,4 +101,4 @@
</button>
</form>
@endif
</li>
</div>
@@ -4,6 +4,7 @@
'disabled' => false,
'icon' => null,
'keyBindings' => null,
'indicator' => null,
'label' => null,
'size' => 'md',
'tag' => 'button',
@@ -32,6 +33,15 @@
'w-4 h-4' => $size === 'sm',
'w-6 h-6' => $size === 'lg',
]);
$indicatorClasses = \Illuminate\Support\Arr::toCssClasses([
'filament-icon-button-indicator absolute rounded-full text-xs inline-block w-4 h-4 -top-0.5 -right-0.5',
'bg-primary-500/10' => $color === 'primary',
'bg-danger-500/10' => $color === 'danger',
'bg-gray-500/10' => $color === 'secondary',
'bg-success-500/10' => $color === 'success',
'bg-warning-500/10' => $color === 'warning',
]);
@endphp
@if ($tag === 'button')
@@ -59,6 +69,12 @@
@endif
<x-dynamic-component :component="$icon" :class="$iconClasses" />
@if ($indicator)
<span class="{{ $indicatorClasses }}">
{{ $indicator }}
</span>
@endif
</button>
@elseif ($tag === 'a')
<a
@@ -83,5 +99,11 @@
@endif
<x-dynamic-component :component="$icon" :class="$iconClasses" />
@if ($indicator)
<span class="{{ $indicatorClasses }}">
{{ $indicator }}
</span>
@endif
</a>
@endif
+3 -1
View File
@@ -35,7 +35,9 @@ class ActionGroup extends ViewComponent
public function getLabel(): ?string
{
return $this->evaluate($this->label);
$label = $this->evaluate($this->label);
return $this->shouldTranslateLabel ? __($label) : $label;
}
public function getActions(): array
+2 -1
View File
@@ -37,6 +37,7 @@ You're now ready to start [building tables](getting-started)!
The package uses the following dependencies:
- [Alpine.js](https://alpinejs.dev)
- [Alpine.js Focus Plugin](https://alpinejs.dev/plugins/focus)
- [Tailwind CSS](https://tailwindcss.com)
- [Tailwind CSS Forms plugin](https://github.com/tailwindlabs/tailwindcss-forms)
- [Tailwind CSS Typography plugin](https://tailwindcss.com/docs/typography-plugin)
@@ -155,7 +156,7 @@ In `/resources/css/app.css`, import `filament/forms` vendor CSS and [Tailwind CS
### Configuring scripts
In `/resources/js/app.js`, import [Alpine.js](https://alpinejs.dev), the `filament/forms`, `filament/notifications` and `@alpinejs/focus` plugins, and register them:
In `/resources/js/app.js`, import [Alpine.js](https://alpinejs.dev), `@alpinejs/focus`, the `filament/forms` and `filament/notifications` plugins, and register them:
```js
import Alpine from 'alpinejs'
+37 -7
View File
@@ -640,12 +640,27 @@ use Filament\Tables\Columns\BadgeColumn;
BadgeColumn::make('status')
->colors([
'primary',
'danger' => fn ($state): bool => $state === 'draft',
'warning' => fn ($state): bool => $state === 'reviewing',
'success' => fn ($state): bool => $state === 'published',
'danger' => static fn ($state): bool => $state === 'draft',
'warning' => static fn ($state): bool => $state === 'reviewing',
'success' => static fn ($state): bool => $state === 'published',
])
```
Or dynamically calculate the color based on the `$record` and / or `$state`:
```php
use Filament\Tables\Columns\BadgeColumn;
BadgeColumn::make('status')
->icon(static function ($state): string {
if ($state === 'published') {
return 'success';
}
return 'secondary';
})
```
Badges may also have an icon:
```php
@@ -668,12 +683,27 @@ use Filament\Tables\Columns\BadgeColumn;
BadgeColumn::make('status')
->icons([
'heroicon-o-x',
'heroicon-o-document' => fn ($state): bool => $state === 'draft',
'heroicon-o-refresh' => fn ($state): bool => $state === 'reviewing',
'heroicon-o-truck' => fn ($state): bool => $state === 'published',
'heroicon-o-document' => static fn ($state): bool => $state === 'draft',
'heroicon-o-refresh' => static fn ($state): bool => $state === 'reviewing',
'heroicon-o-truck' => static fn ($state): bool => $state === 'published',
])
```
Or dynamically calculate the icon based on the `$record` and / or `$state`:
```php
use Filament\Tables\Columns\BadgeColumn;
BadgeColumn::make('status')
->icon(static function ($state): string {
if ($state === 'published') {
return 'heroicon-o-truck';
}
return 'heroicon-o-x';
})
```
You may set the position of an icon using `iconPosition()`:
```php
@@ -704,7 +734,7 @@ Be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#arra
```php
use Illuminate\Database\Eloquent\Model;
class BlogPost extends Model
class Post extends Model
{
protected $casts = [
'tags' => 'array',
@@ -94,10 +94,6 @@ return [
'tooltip' => 'إعادة ضبط المصفيات',
],
'close' => [
'label' => 'غلق',
],
],
'indicator' => 'المصفيات النشطة',
@@ -71,10 +71,6 @@ return [
'label' => 'Resetujte filtere',
],
'close' => [
'label' => 'Zatvori',
],
],
'multi_select' => [
@@ -71,10 +71,6 @@ return [
'label' => 'Resetovat filtry',
],
'close' => [
'label' => 'Zavřít',
],
],
'multi_select' => [
@@ -102,10 +102,6 @@ return [
'label' => 'Filter zurücksetzen',
],
'close' => [
'label' => 'Schließen',
],
],
'indicator' => 'Aktive Filter',
@@ -102,10 +102,6 @@ return [
'label' => 'Reset filters',
],
'close' => [
'label' => 'Close',
],
],
'indicator' => 'Active filters',
+17 -6
View File
@@ -28,7 +28,13 @@ return [
'fields' => [
'records_per_page' => [
'label' => 'por página',
'options' => [
'all' => 'Todos',
],
],
],
@@ -83,12 +89,17 @@ return [
'buttons' => [
'reset' => [
'label' => 'Resetea los filtros',
'remove' => [
'label' => 'Quitar filtro',
],
'close' => [
'label' => 'Cerrar',
'remove_all' => [
'label' => 'Quitar todos los filtros',
'tooltip' => 'Quitar todos los filtros',
],
'reset' => [
'label' => 'Resetea los filtros',
],
],
@@ -109,7 +120,7 @@ return [
'only_trashed' => 'Solo registros eliminados',
'with_trashed' => 'Con resgistros eliminados',
'with_trashed' => 'Con registros eliminados',
'without_trashed' => 'Sin registros eliminados',
@@ -126,7 +137,7 @@ return [
'buttons' => [
'select_all' => [
'label' => 'Selecciona los :count',
'label' => 'Selecciona todos :count',
],
'deselect_all' => [
@@ -71,10 +71,6 @@ return [
'label' => 'حذف فیلترها',
],
'close' => [
'label' => 'بستن',
],
],
'multi_select' => [
@@ -88,10 +88,6 @@ return [
'tooltip' => 'Réinitialiser',
],
'close' => [
'label' => 'Fermer',
],
],
'indicator' => 'Filtres actifs',
@@ -71,10 +71,6 @@ return [
'label' => 'Alapértelmezés',
],
'close' => [
'label' => 'Bezárás',
],
],
'multi_select' => [
@@ -71,10 +71,6 @@ return [
'label' => 'Վերականգնել ֆիլտրերը',
],
'close' => [
'label' => 'Փակել',
],
],
'multi_select' => [
@@ -88,10 +88,6 @@ return [
'tooltip' => 'Atur ulang filter',
],
'close' => [
'label' => 'Tutup',
],
],
'indicator' => 'Filter aktif',
@@ -88,10 +88,6 @@ return [
'tooltip' => 'Resetta filtri',
],
'close' => [
'label' => 'Chiudi',
],
],
'indicator' => 'Filtri attivi',
@@ -71,10 +71,6 @@ return [
'label' => 'リセット',
],
'close' => [
'label' => '閉じる',
],
],
'multi_select' => [
@@ -94,10 +94,6 @@ return [
'tooltip' => 'Filters resetten',
],
'close' => [
'label' => 'Sluiten',
],
],
'indicator' => 'Actieve filters',
@@ -102,10 +102,6 @@ return [
'label' => 'Zresetuj filtry',
],
'close' => [
'label' => 'Zamknij',
],
],
'indicator' => 'Aktywne filtry',
@@ -2,6 +2,14 @@
return [
'columns' => [
'tags' => [
'more' => 'e :count mais',
],
],
'fields' => [
'search_query' => [
@@ -20,7 +28,13 @@ return [
'fields' => [
'records_per_page' => [
'label' => 'por página',
'options' => [
'all' => 'Todas',
],
],
],
@@ -45,6 +59,14 @@ return [
'buttons' => [
'disable_reordering' => [
'label' => 'Concluir a reordenação de registros',
],
'enable_reordering' => [
'label' => 'Reordenar registros',
],
'filter' => [
'label' => 'Filtrar',
],
@@ -53,6 +75,10 @@ return [
'label' => 'Ações abertas',
],
'toggle_columns' => [
'label' => 'Alternar colunas',
],
],
'empty' => [
@@ -63,12 +89,27 @@ return [
'buttons' => [
'remove' => [
'label' => 'Remover filtro',
],
'remove_all' => [
'label' => 'Remover todos os filtros',
'tooltip' => 'Remover todos os filtros',
],
'reset' => [
'label' => 'Limpar filtros',
],
'close' => [
'label' => 'Fechar',
],
],
'indicator' => 'Filtros ativos',
'multi_select' => [
'placeholder' => 'Todos',
],
@@ -77,8 +118,22 @@ return [
'placeholder' => 'Todos',
],
'trashed' => [
'label' => 'Registros excluídos',
'only_trashed' => 'Somente registros excluídos',
'with_trashed' => 'Exibir registros excluídos',
'without_trashed' => 'Não exibir registros excluídos',
],
],
'reorder_indicator' => 'Arraste e solte os registros na ordem.',
'selection_indicator' => [
'selected_count' => '1 registro selecionado.|:count registros selecionados.',
@@ -71,10 +71,6 @@ return [
'label' => 'Resetare filtre',
],
'close' => [
'label' => 'Închidere',
],
],
'multi_select' => [
+17 -4
View File
@@ -28,7 +28,13 @@ return [
'fields' => [
'records_per_page' => [
'label' => 'на страницу',
'options' => [
'all' => 'Все',
],
],
],
@@ -83,16 +89,23 @@ return [
'buttons' => [
'remove' => [
'label' => 'Удалить фильтр',
],
'remove_all' => [
'label' => 'Отчистить фильтры',
'tooltip' => 'Отчистить фильтры',
],
'reset' => [
'label' => 'Сбросить фильтры',
],
'close' => [
'label' => 'Закрыть',
],
],
'indicator' => 'Активные фильтры',
'multi_select' => [
'placeholder' => 'Все',
],
@@ -71,10 +71,6 @@ return [
'label' => 'Återställ filter',
],
'close' => [
'label' => 'Stäng',
],
],
'multi_select' => [
@@ -79,10 +79,6 @@ return [
'label' => 'Filtrelemeleri sıfırla',
],
'close' => [
'label' => 'Kapat',
],
],
'multi_select' => [
+21 -8
View File
@@ -28,7 +28,13 @@ return [
'fields' => [
'records_per_page' => [
'label' => 'на сторінку',
'options' => [
'all' => 'Всі',
],
],
],
@@ -76,23 +82,30 @@ return [
],
'empty' => [
'heading' => 'Не знайдено записів',
'heading' => 'не знайдено записів',
],
'filters' => [
'buttons' => [
'remove' => [
'label' => 'Видалити фільтр',
],
'remove_all' => [
'label' => 'Очистити фільтри',
'tooltip' => 'Очистити фільтри',
],
'reset' => [
'label' => 'Скинути фільтри',
],
'close' => [
'label' => 'Закрити',
],
],
'indicator' => 'Активні фільтри',
'multi_select' => [
'placeholder' => 'Всі',
],
@@ -103,13 +116,13 @@ return [
'trashed' => [
'label' => 'Видалені записи',
'label' => 'Віддалені записи',
'only_trashed' => 'Тільки видалені записи',
'with_trashed' => 'З видаленими записами',
'with_trashed' => 'З віддаленими записами',
'without_trashed' => 'Без видалених записів',
'without_trashed' => 'Без віддалених записів',
],
@@ -88,10 +88,6 @@ return [
'tooltip' => 'Đặt lại bộ lọc',
],
'close' => [
'label' => 'Đóng',
],
],
'indicator' => 'Bộ lọc đang kích hoạt',
@@ -71,10 +71,6 @@ return [
'label' => '重置筛选条件',
],
'close' => [
'label' => '关闭',
],
],
'multi_select' => [
@@ -71,10 +71,6 @@ return [
'label' => '重設篩選',
],
'close' => [
'label' => '關閉',
],
],
'multi_select' => [
@@ -6,7 +6,7 @@
'primary' => \Illuminate\Support\Arr::toCssClasses(['text-primary-700 bg-primary-500/10', 'dark:text-primary-500' => config('tables.dark_mode')]),
'success' => \Illuminate\Support\Arr::toCssClasses(['text-success-700 bg-success-500/10', 'dark:text-success-500' => config('tables.dark_mode')]),
'warning' => \Illuminate\Support\Arr::toCssClasses(['text-warning-700 bg-warning-500/10', 'dark:text-warning-500' => config('tables.dark_mode')]),
null => \Illuminate\Support\Arr::toCssClasses(['text-gray-700 bg-gray-500/10', 'dark:text-gray-300 dark:bg-gray-500/20' => config('tables.dark_mode')]),
null, 'secondary' => \Illuminate\Support\Arr::toCssClasses(['text-gray-700 bg-gray-500/10', 'dark:text-gray-300 dark:bg-gray-500/20' => config('tables.dark_mode')]),
default => $getStateColor(),
};
@@ -2,31 +2,15 @@
'actions',
])
<div
x-data="{}"
x-cloak
{{ $attributes->class(['filament-tables-bulk-actions relative']) }}
<x-tables::dropdown
{{ $attributes->class(['filament-tables-bulk-actions']) }}
placement="bottom-start"
>
<x-tables::bulk-actions.trigger />
<x-slot name="trigger">
<x-tables::bulk-actions.trigger />
</x-slot>
<div
x-ref="panel"
x-float.placement.bottom-start.flip.offset="{ offset: 8 }"
x-transition:enter="transition"
x-transition:enter-start="-translate-y-1 opacity-0"
x-transition:enter-end="translate-y-0 opacity-100"
x-transition:leave="transition"
x-transition:leave-start="translate-y-0 opacity-100"
x-transition:leave-end="-translate-y-1 opacity-0"
class="absolute z-10 hidden shadow-xl rounded-xl w-52"
>
<ul @class([
'py-1 space-y-1 overflow-hidden bg-white shadow rounded-xl',
'dark:border-gray-600 dark:bg-gray-700' => config('tables.dark_mode'),
])>
@foreach ($actions as $action)
{{ $action }}
@endforeach
</ul>
</div>
</div>
@foreach ($actions as $action)
{{ $action }}
@endforeach
</x-tables::dropdown>
@@ -1,6 +1,5 @@
<x-tables::icon-button
icon="heroicon-o-dots-vertical"
x-on:click="$refs.panel.toggle"
:label="__('tables::table.buttons.open_actions.label')"
{{ $attributes->class(['filament-tables-bulk-actions-trigger']) }}
/>
@@ -0,0 +1,10 @@
@captureSlots([
'trigger',
])
<x-filament-support::dropdown
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->merge($slots)"
:dark-mode="config('tables.dark_mode')"
>
{{ $slot }}
</x-filament-support::dropdown>
@@ -2,7 +2,10 @@
'form',
])
<div class="filament-tables-filters-form space-y-6" x-data="{}">
<div
{{ $attributes->class(['filament-tables-filters-form space-y-6']) }}
x-data
>
{{ $form }}
<div class="text-right">
@@ -1,56 +1,22 @@
@props([
'form',
'width' => 'sm',
'indicatorsCount' => null,
])
<div
x-data="{}"
{{ $attributes->class(['filament-tables-filters relative inline-block']) }}
<x-tables::dropdown
{{ $attributes->class(['filament-tables-filters']) }}
placement="bottom-end"
shift
width="xs"
wire:key="{{ $this->id }}.table.filters"
>
<x-tables::filters.trigger />
<x-slot name="trigger">
<x-tables::filters.trigger :indicators-count="$indicatorsCount" />
</x-slot>
<div
x-ref="popoverPanel"
x-float.placement.bottom-end.offset="{ offset: 8 }"
wire:ignore.self
wire:key="{{ $this->id }}.table.filters.panel"
x-cloak
x-transition:enter="ease duration-300"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="ease duration-300"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-2"
@class([
'absolute hidden z-10 w-screen top-full transition',
match ($width) {
'xs' => 'max-w-xs',
'md' => 'max-w-md',
'lg' => 'max-w-lg',
'xl' => 'max-w-xl',
'2xl' => 'max-w-2xl',
'3xl' => 'max-w-3xl',
'4xl' => 'max-w-4xl',
'5xl' => 'max-w-5xl',
'6xl' => 'max-w-6xl',
'7xl' => 'max-w-7xl',
default => 'max-w-sm',
},
])
>
<div @class([
'px-6 py-4 bg-white border border-gray-300 space-y-6 shadow-xl rounded-xl',
'dark:bg-gray-800 dark:border-gray-700' => config('tables.dark_mode'),
]) wire:ignore.self>
<x-tables::icon-button
icon="heroicon-o-x"
x-on:click="$refs.popoverPanel.close"
:label=" __('tables::table.filters.buttons.close.label')"
color="secondary"
{{ $attributes->class(['absolute top-3 right-3 rtl:right-auto rtl:left-3']) }}
/>
<x-tables::filters :form="$form" />
</div>
</div>
</div>
<x-tables::filters
class="p-4"
:form="$form"
/>
</x-tables::dropdown>
@@ -1,6 +1,10 @@
@props([
'indicatorsCount' => null,
])
<x-tables::icon-button
icon="heroicon-o-filter"
x-on:click="$refs.popoverPanel.toggle"
:label="__('tables::table.buttons.filter.label')"
:indicator="$indicatorsCount"
{{ $attributes->class(['filament-tables-filters-trigger']) }}
/>
@@ -3,46 +3,17 @@
'width' => 'sm',
])
<div
x-data
{{ $attributes->class(['filament-tables-column-toggling relative inline-block']) }}
<x-tables::dropdown
{{ $attributes->class(['filament-tables-column-toggling']) }}
placement="bottom-end"
shift
wire:key="{{ $this->id }}.table.toggle"
>
<x-tables::toggleable.trigger />
<x-slot name="trigger">
<x-tables::toggleable.trigger />
</x-slot>
<div
x-ref="toggleablePanel"
x-float.placement.bottom-end.offset="{ offset: 8 }"
wire:ignore.self
wire:key="{{ $this->id }}.table.toggle.panel"
x-cloak
x-transition:enter="ease duration-300"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="ease duration-300"
x-transition:leave-start="opacity-100 translate-y-0"
x-transition:leave-end="opacity-0 translate-y-2"
@class([
'absolute hidden z-10 w-screen top-full transition',
match ($width) {
'xs' => 'max-w-xs',
'md' => 'max-w-md',
'lg' => 'max-w-lg',
'xl' => 'max-w-xl',
'2xl' => 'max-w-2xl',
'3xl' => 'max-w-3xl',
'4xl' => 'max-w-4xl',
'5xl' => 'max-w-5xl',
'6xl' => 'max-w-6xl',
'7xl' => 'max-w-7xl',
default => 'max-w-sm',
},
])
>
<div @class([
'px-6 py-4 bg-white border border-gray-300 space-y-6 shadow-xl rounded-xl',
'dark:bg-gray-800 dark:border-gray-700' => config('tables.dark_mode'),
])>
{{ $form }}
</div>
<div class="p-4">
{{ $form }}
</div>
</div>
</x-tables::dropdown>
@@ -1,6 +1,5 @@
<x-tables::icon-button
icon="heroicon-o-view-boards"
x-on:click="$refs.toggleablePanel.toggle"
:label="__('tables::table.buttons.toggle_columns.label')"
{{ $attributes->class(['filament-tables-column-toggling-trigger']) }}
/>
@@ -8,6 +8,10 @@
$columns = $getColumns();
$content = $getContent();
$contentFooter = $getContentFooter();
$filterIndicators = collect($getFilters())
->mapWithKeys(fn (\Filament\Tables\Filters\BaseFilter $filter): array => [$filter->getName() => $filter->getIndicators()])
->filter(fn (array $indicators): bool => count($indicators))
->all();
$header = $getHeader();
$headerActions = $getHeaderActions();
$heading = $getHeading();
@@ -296,6 +300,7 @@
<x-tables::filters.popover
:form="$getFiltersForm()"
:width="$getFiltersFormWidth()"
:indicators-count="count(\Illuminate\Support\Arr::flatten($filterIndicators))"
class="shrink-0"
/>
@endif
@@ -337,7 +342,7 @@
@endif
<x-tables::filters.indicators
:indicators="collect($getFilters())->mapWithKeys(fn (\Filament\Tables\Filters\BaseFilter $filter): array => [$filter->getName() => $filter->getIndicators()])->filter(fn (array $indicators): bool => count($indicators))->all()"
:indicators="$filterIndicators"
:class="\Illuminate\Support\Arr::toCssClasses([
'border-t',
'dark:border-gray-700' => config('tables.dark_mode'),
@@ -3,38 +3,46 @@
namespace Filament\Tables\Columns\Concerns;
use Closure;
use Filament\Tables\Columns\Column;
use Illuminate\Database\Eloquent\Model;
trait HasColors
{
protected array | Closure $colors = [];
protected string | Closure | null $color = null;
public function color(string | Closure | null $color): static
{
$this->color = $color;
return $this;
}
public function colors(array | Closure $colors): static
{
$this->colors = $colors;
$this->color(function (Column $column, Model $record, $state) use ($colors) {
$colors = $column->evaluate($colors);
$stateColor = null;
foreach ($colors as $color => $condition) {
if (is_numeric($color)) {
$stateColor = $condition;
} elseif ($condition instanceof Closure && $condition($state, $record)) {
$stateColor = $color;
} elseif ($condition === $state) {
$stateColor = $color;
}
}
return $stateColor;
});
return $this;
}
public function getStateColor(): ?string
{
$state = $this->getState();
$stateColor = null;
foreach ($this->getColors() as $color => $condition) {
if (is_numeric($color)) {
$stateColor = $condition;
} elseif ($condition instanceof Closure && $condition($state, $this->getRecord())) {
$stateColor = $color;
} elseif ($condition === $state) {
$stateColor = $color;
}
}
return $stateColor;
}
public function getColors(): array
{
return $this->evaluate($this->colors);
return $this->evaluate($this->color, [
'state' => $this->getState(),
]);
}
}
@@ -3,16 +3,40 @@
namespace Filament\Tables\Columns\Concerns;
use Closure;
use Filament\Tables\Columns\Column;
use Illuminate\Database\Eloquent\Model;
trait HasIcons
{
protected array | Closure $icons = [];
protected string | Closure | null $icon = null;
protected string | Closure | null $iconPosition = null;
public function icon(string | Closure | null $icon): static
{
$this->icon = $icon;
return $this;
}
public function icons(array | Closure $icons): static
{
$this->icons = $icons;
$this->icon(function (Column $column, Model $record, $state) use ($icons) {
$icons = $column->evaluate($icons);
$stateIcon = null;
foreach ($icons as $icon => $condition) {
if (is_numeric($icon)) {
$stateIcon = $condition;
} elseif ($condition instanceof Closure && $condition($state, $record)) {
$stateIcon = $icon;
} elseif ($condition === $state) {
$stateIcon = $icon;
}
}
return $stateIcon;
});
return $this;
}
@@ -26,25 +50,9 @@ trait HasIcons
public function getStateIcon(): ?string
{
$state = $this->getState();
$stateIcon = null;
foreach ($this->getIcons() as $icon => $condition) {
if (is_numeric($icon)) {
$stateIcon = $condition;
} elseif ($condition instanceof Closure && $condition($state, $this->getRecord())) {
$stateIcon = $icon;
} elseif ($condition === $state) {
$stateIcon = $icon;
}
}
return $stateIcon;
}
public function getIcons(): array
{
return $this->evaluate($this->icons);
return $this->evaluate($this->icon, [
'state' => $this->getState(),
]);
}
public function getIconPosition(): string
@@ -24,7 +24,7 @@ class MultiSelectFilter extends BaseFilter
$this->placeholder(__('tables::table.filters.multi_select.placeholder'));
$this->indicateUsing(function (array $state): array {
if (blank($state['value'] ?? null)) {
if (blank($state['values'] ?? null)) {
return [];
}
+1 -1
View File
@@ -25,7 +25,7 @@ class Table extends ViewComponent
protected string $viewIdentifier = 'table';
public const LOADING_TARGETS = ['previousPage', 'nextPage', 'gotoPage', 'sortTable', 'tableFilters', 'resetTableFiltersForm', 'tableSearchQuery', 'tableRecordsPerPage', '$set'];
public const LOADING_TARGETS = ['previousPage', 'nextPage', 'gotoPage', 'sortTable', 'tableFilters', 'resetTableFiltersForm', 'tableSearchQuery', 'tableColumnSearchQueries', 'tableRecordsPerPage', '$set'];
final public function __construct(HasTable $livewire)
{
+136
View File
@@ -0,0 +1,136 @@
<?php
use Filament\Forms\Components\TextInput;
use Filament\Tests\Forms\Fixtures\Livewire;
use Filament\Tests\TestCase;
use Illuminate\Contracts\View\View;
use function Pest\Livewire\livewire;
uses(TestCase::class);
it('has a form with the default name \'form\'', function () {
livewire(TestComponentWithForm::class)
->assertFormExists();
});
it('can have forms with non-default names', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormExists('fooForm')
->assertFormExists('barForm');
});
it('has fields', function () {
livewire(TestComponentWithForm::class)
->assertFormFieldExists('title');
});
it('has fields on multiple forms', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormFieldExists('title', 'fooForm')
->assertFormFieldExists('title', 'barForm');
});
it('can have disabled fields', function () {
livewire(TestComponentWithForm::class)
->assertFormFieldIsDisabled('disabled');
});
it('can have disabled fields on multiple forms', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormFieldIsDisabled('disabled', 'fooForm')
->assertFormFieldIsDisabled('disabled', 'barForm');
});
it('can have enabled fields', function () {
livewire(TestComponentWithForm::class)
->assertFormFieldIsEnabled('enabled');
});
it('can have enabled fields on multiple forms', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormFieldIsEnabled('enabled', 'fooForm')
->assertFormFieldIsEnabled('enabled', 'barForm');
});
it('can have hidden fields', function () {
livewire(TestComponentWithForm::class)
->assertFormFieldIsHidden('hidden');
});
it('can have hidden fields on multiple forms', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormFieldIsHidden('hidden', 'fooForm')
->assertFormFieldIsHidden('hidden', 'barForm');
});
it('can have visible fields', function () {
livewire(TestComponentWithForm::class)
->assertFormFieldIsVisible('visible');
});
it('can have visible fields on multiple forms', function () {
livewire(TestComponentWithMultipleForms::class)
->assertFormFieldIsVisible('visible', 'fooForm')
->assertFormFieldIsVisible('visible', 'barForm');
});
class TestComponentWithForm extends Livewire
{
public function getFormSchema(): array
{
return [
TextInput::make('title'),
TextInput::make('disabled')
->disabled(),
TextInput::make('enabled'),
TextInput::make('hidden')
->hidden(),
TextInput::make('visible'),
];
}
public function render(): View
{
return view('forms.fixtures.form');
}
}
class TestComponentWithMultipleForms extends Livewire
{
protected function getForms(): array
{
return [
'fooForm' => $this->makeForm()
->schema($this->getSchemaForForms()),
'barForm' => $this->makeForm()
->schema($this->getSchemaForForms()),
];
}
private function getSchemaForForms(): array
{
return [
TextInput::make('title'),
TextInput::make('disabled')
->disabled(),
TextInput::make('enabled'),
TextInput::make('hidden')
->hidden(),
TextInput::make('visible'),
];
}
public function render(): View
{
return view('forms.fixtures.form');
}
}