@navette-js/support 1.0.0-beta.4 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +1 -0
- package/data/lang.en-fr.json +184 -10
- package/icons/filament/m-pencil-slash.svg +4 -0
- package/icons/filament/o-align-center.svg +5 -0
- package/icons/filament/o-align-end.svg +5 -0
- package/icons/filament/o-align-justify.svg +5 -0
- package/icons/filament/o-align-start.svg +5 -0
- package/icons/filament/o-clear-formatting.svg +6 -0
- package/icons/filament/o-code-block.svg +5 -0
- package/icons/filament/o-code.svg +5 -0
- package/icons/filament/o-columns-delete.svg +11 -0
- package/icons/filament/o-columns.svg +10 -0
- package/icons/filament/o-details.svg +5 -0
- package/icons/filament/o-h1.svg +11 -0
- package/icons/filament/o-h2.svg +11 -0
- package/icons/filament/o-h3.svg +12 -0
- package/icons/filament/o-h4.svg +11 -0
- package/icons/filament/o-h5.svg +11 -0
- package/icons/filament/o-h6.svg +12 -0
- package/icons/filament/o-heading.svg +9 -0
- package/icons/filament/o-highlight.svg +6 -0
- package/icons/filament/o-lead.svg +6 -0
- package/icons/filament/o-merge-tag.svg +7 -0
- package/icons/filament/o-paragraph.svg +5 -0
- package/icons/filament/o-small.svg +5 -0
- package/icons/filament/o-subscript.svg +5 -0
- package/icons/filament/o-superscript.svg +5 -0
- package/icons/filament/o-table-add-column-after.svg +5 -0
- package/icons/filament/o-table-add-column-before.svg +5 -0
- package/icons/filament/o-table-add-row-after.svg +5 -0
- package/icons/filament/o-table-add-row-before.svg +5 -0
- package/icons/filament/o-table-delete-column.svg +5 -0
- package/icons/filament/o-table-delete-row.svg +5 -0
- package/icons/filament/o-table-delete.svg +6 -0
- package/icons/filament/o-table-merge-cells.svg +7 -0
- package/icons/filament/o-table-split-cell.svg +6 -0
- package/icons/filament/o-table-toggle-header-cell.svg +4 -0
- package/icons/filament/o-table-toggle-header-row.svg +7 -0
- package/icons/filament/o-table.svg +5 -0
- package/lib/components.d.ts +6 -0
- package/lib/components.js +130 -0
- package/lib/index.d.ts +25 -1
- package/lib/index.js +65 -8
- package/lib/ui.d.ts +2 -0
- package/lib/ui.js +32 -1
- package/package.json +1 -1
package/THIRD-PARTY-NOTICES.md
CHANGED
|
@@ -7,6 +7,7 @@ Navette is an independent project, not affiliated with or endorsed by the Filame
|
|
|
7
7
|
| [Filament](https://github.com/filamentphp/filament) © Filament | HTML markup derived from its Blade views, compiled CSS and JavaScript (`@navette-js/panels/dist/filament`), English translations (`@navette-js/support/data`), image editor icons (`@navette-js/support/icons/filament`) | MIT | `packages/panels/dist/FILAMENT-LICENSE.md`, `packages/support/icons/filament/LICENSE.md` |
|
|
8
8
|
| [Livewire](https://github.com/livewire/livewire) © Caleb Porzio | Client script `livewire.js` (`@navette-js/wire/vendor`); the server runtime follows its protocol | MIT | `packages/wire/vendor/LIVEWIRE-LICENSE.md` |
|
|
9
9
|
| [Heroicons](https://github.com/tailwindlabs/heroicons) | SVG icons (`@navette-js/support/icons`) | MIT | `packages/support/icons/HEROICONS-LICENSE.md` |
|
|
10
|
+
| [QR Code generator library](https://www.nayuki.io/page/qr-code-generator-library) © Project Nayuki | Structure of the QR Code encoder (`@navette-js/panels`, `qr-code.ts`) | MIT | header of `packages/panels/src/qr-code.ts` |
|
|
10
11
|
| [Inter](https://github.com/rsms/inter) © The Inter Project Authors | Default font files (`@navette-js/panels/dist/filament/fonts`) | SIL Open Font License 1.1 | `packages/panels/dist/filament/fonts/INTER-LICENSE.txt` |
|
|
11
12
|
|
|
12
13
|
Runtime dependencies installed from npm (Express, Knex, Objection, better-sqlite3, Tiptap, EJS, Busboy…) keep their own licenses.
|
package/data/lang.en-fr.json
CHANGED
|
@@ -956,9 +956,22 @@
|
|
|
956
956
|
},
|
|
957
957
|
"auth/multi-factor/app/actions/set-up": {
|
|
958
958
|
"label": "Set up",
|
|
959
|
-
"modal.0": "{{but}}{{you\\}}ll need them if you lose access to your authenticator app:",
|
|
960
959
|
"modal.heading": "Set up authenticator app",
|
|
961
|
-
"modal.description": "
|
|
960
|
+
"modal.description": "You'll need an app like Google Authenticator (<x-filament::link href=\"https://itunes.apple.com/us/app/google-authenticator/id388497605\" target=\"_blank\">iOS</x-filament::link>, <x-filament::link href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" target=\"_blank\">Android</x-filament::link>) to complete this process.",
|
|
961
|
+
"modal.content.qr_code.instruction": "Scan this QR code with your authenticator app:",
|
|
962
|
+
"modal.content.qr_code.alt": "QR code to scan with an authenticator app",
|
|
963
|
+
"modal.content.text_code.instruction": "Or enter this code manually:",
|
|
964
|
+
"modal.content.text_code.messages.copied": "Copied",
|
|
965
|
+
"modal.content.recovery_codes.instruction": "Please save the following recovery codes in a safe place. They will only be shown once, but you'll need them if you lose access to your authenticator app:",
|
|
966
|
+
"modal.form.password.label": "Current password",
|
|
967
|
+
"modal.form.password.validation_attribute": "current password",
|
|
968
|
+
"modal.form.code.label": "Enter the 6-digit code from the authenticator app",
|
|
969
|
+
"modal.form.code.validation_attribute": "code",
|
|
970
|
+
"modal.form.code.below_content": "You will need to enter the 6-digit code from your authenticator app each time you sign in or perform sensitive actions.",
|
|
971
|
+
"modal.form.code.messages.invalid": "The code you entered is invalid.",
|
|
972
|
+
"modal.form.code.messages.rate_limited": "Too many attempts. Please try again later.",
|
|
973
|
+
"modal.actions.submit.label": "Enable authenticator app",
|
|
974
|
+
"notifications.enabled.title": "Authenticator app has been enabled"
|
|
962
975
|
},
|
|
963
976
|
"auth/multi-factor/app/provider": {
|
|
964
977
|
"management_schema.actions.label": "Authenticator app",
|
|
@@ -1060,7 +1073,12 @@
|
|
|
1060
1073
|
"notifications.saved.title": "Saved",
|
|
1061
1074
|
"notifications.throttled.title": "Too many requests. Please try again in :seconds seconds.",
|
|
1062
1075
|
"notifications.throttled.body": "Please try again in :seconds seconds.",
|
|
1063
|
-
"actions.cancel.label": "Cancel"
|
|
1076
|
+
"actions.cancel.label": "Cancel",
|
|
1077
|
+
"sections.information.heading": "Profile information",
|
|
1078
|
+
"sections.information.description": "Your name and the email address you sign in with.",
|
|
1079
|
+
"sections.password.heading": "Password",
|
|
1080
|
+
"sections.password.description": "Use a long, random password to keep your account secure.",
|
|
1081
|
+
"multi_factor_authentication.description": "A second step after your password: a code from an app, a code by email or a security key."
|
|
1064
1082
|
},
|
|
1065
1083
|
"auth/pages/email-verification/email-verification-prompt": {
|
|
1066
1084
|
"title": "Verify your email address",
|
|
@@ -1210,6 +1228,77 @@
|
|
|
1210
1228
|
"widgets/filament-info-widget": {
|
|
1211
1229
|
"actions.open_documentation.label": "Documentation",
|
|
1212
1230
|
"actions.open_github.label": "GitHub"
|
|
1231
|
+
},
|
|
1232
|
+
"auth/multi-factor/security-keys/provider": {
|
|
1233
|
+
"login_form.label": "Use a security key",
|
|
1234
|
+
"login_form.credential.label": "Security key",
|
|
1235
|
+
"login_form.credential.validation_attribute": "security key",
|
|
1236
|
+
"login_form.credential.messages.invalid": "The security key could not be verified.",
|
|
1237
|
+
"management_schema.actions.label": "Security keys",
|
|
1238
|
+
"management_schema.actions.below_content": "Use a physical security key or a passkey saved on your device to verify your identity.",
|
|
1239
|
+
"management_schema.actions.messages.enabled": "Enabled",
|
|
1240
|
+
"management_schema.actions.messages.disabled": "Disabled",
|
|
1241
|
+
"management_schema.actions.messages.added": "Added on :date",
|
|
1242
|
+
"management_schema.actions.messages.last_used": "Last used on :date"
|
|
1243
|
+
},
|
|
1244
|
+
"auth/multi-factor/security-keys/actions/register": {
|
|
1245
|
+
"label": "Add a security key",
|
|
1246
|
+
"modal.heading": "Add a security key",
|
|
1247
|
+
"modal.description": "Give the key a name, then follow your browser's instructions.",
|
|
1248
|
+
"modal.form.name.label": "Name",
|
|
1249
|
+
"modal.form.name.placeholder": "My security key",
|
|
1250
|
+
"modal.form.credential.label": "Security key",
|
|
1251
|
+
"modal.form.credential.validation_attribute": "security key",
|
|
1252
|
+
"modal.form.credential.messages.invalid": "The security key could not be registered. Try again.",
|
|
1253
|
+
"modal.form.credential.messages.rate_limited": "Too many attempts. Please try again later.",
|
|
1254
|
+
"modal.form.password.label": "Current password",
|
|
1255
|
+
"modal.form.password.validation_attribute": "current password",
|
|
1256
|
+
"modal.actions.submit.label": "Add security key",
|
|
1257
|
+
"notifications.registered.title": "Security key added"
|
|
1258
|
+
},
|
|
1259
|
+
"auth/multi-factor/security-keys/actions/remove": {
|
|
1260
|
+
"label": "Remove a key",
|
|
1261
|
+
"modal.heading": "Remove a security key",
|
|
1262
|
+
"modal.description": "The key will no longer be accepted to sign in.",
|
|
1263
|
+
"modal.form.key.label": "Key",
|
|
1264
|
+
"modal.form.password.label": "Current password",
|
|
1265
|
+
"modal.form.password.validation_attribute": "current password",
|
|
1266
|
+
"modal.actions.submit.label": "Remove key",
|
|
1267
|
+
"notifications.removed.title": "Security key removed"
|
|
1268
|
+
},
|
|
1269
|
+
"auth/multi-factor/security-keys/field": {
|
|
1270
|
+
"actions.register.label": "Use my security key",
|
|
1271
|
+
"actions.authenticate.label": "Use my security key",
|
|
1272
|
+
"messages.waiting": "Follow your browser's instructions…",
|
|
1273
|
+
"messages.registered": "Security key ready: submit the form to add it.",
|
|
1274
|
+
"messages.verified": "Security key verified.",
|
|
1275
|
+
"messages.cancelled": "The operation was cancelled or timed out.",
|
|
1276
|
+
"messages.unsupported": "This browser does not support security keys.",
|
|
1277
|
+
"messages.failed": "The security key could not be used. Try again."
|
|
1278
|
+
},
|
|
1279
|
+
"errors": {
|
|
1280
|
+
"label": "Error :code",
|
|
1281
|
+
"actions.home": "Back to home",
|
|
1282
|
+
"actions.back": "Go back",
|
|
1283
|
+
"actions.retry": "Try again",
|
|
1284
|
+
"actions.login": "Sign in",
|
|
1285
|
+
"details": "Error details",
|
|
1286
|
+
"401.title": "Sign in to board",
|
|
1287
|
+
"401.description": "You need to be signed in to open this page.",
|
|
1288
|
+
"403.title": "This line is closed to you",
|
|
1289
|
+
"403.description": "You don’t have permission to open this page. If you think you should, ask an administrator.",
|
|
1290
|
+
"403.invalid_link": "This link is invalid or has expired.",
|
|
1291
|
+
"403.email_change_blocked": "This email address change was blocked.",
|
|
1292
|
+
"404.title": "Lost in the clouds",
|
|
1293
|
+
"404.description": "The page you are looking for doesn’t exist or has been moved.",
|
|
1294
|
+
"419.title": "Your cabin has left",
|
|
1295
|
+
"419.description": "This page expired after a long time without activity. Reload it and try again.",
|
|
1296
|
+
"429.title": "Rush hour",
|
|
1297
|
+
"429.description": "Too many requests in a short time. Wait a moment before trying again.",
|
|
1298
|
+
"500.title": "The cable snapped",
|
|
1299
|
+
"500.description": "Something went wrong on our side. Try again in a few moments.",
|
|
1300
|
+
"503.title": "Line under maintenance",
|
|
1301
|
+
"503.description": "We’re servicing the line. We’ll be back very soon."
|
|
1213
1302
|
}
|
|
1214
1303
|
},
|
|
1215
1304
|
"fr": {
|
|
@@ -1257,11 +1346,20 @@
|
|
|
1257
1346
|
"auth/multi-factor/app/actions/set-up": {
|
|
1258
1347
|
"label": "Configurer",
|
|
1259
1348
|
"modal.heading": "Configurer l'application d'authentification",
|
|
1260
|
-
"modal.description": "
|
|
1261
|
-
"modal.
|
|
1262
|
-
"
|
|
1263
|
-
"text_code.
|
|
1264
|
-
"
|
|
1349
|
+
"modal.description": "Vous aurez besoin d'une application comme Google Authenticator (<x-filament::link href=\"https://itunes.apple.com/us/app/google-authenticator/id388497605\" target=\"_blank\">iOS</x-filament::link>, <x-filament::link href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\" target=\"_blank\">Android</x-filament::link>) pour compléter cette procédure.",
|
|
1350
|
+
"modal.content.qr_code.instruction": "Scannez ce QR code avec votre application d'authentification :",
|
|
1351
|
+
"modal.content.qr_code.alt": "QR code à scanner avec une application d'authentification",
|
|
1352
|
+
"modal.content.text_code.instruction": "Ou entrez ce code manuellement :",
|
|
1353
|
+
"modal.content.text_code.messages.copied": "Copié",
|
|
1354
|
+
"modal.content.recovery_codes.instruction": "Veuillez enregistrer les codes de récupération suivants dans un endroit sécurisé. Ils ne seront affichés qu'une fois, mais vous en aurez besoin si vous perdez l'accès à votre application d'authentification :",
|
|
1355
|
+
"modal.form.password.label": "Mot de passe actuel",
|
|
1356
|
+
"modal.form.password.validation_attribute": "mot de passe actuel",
|
|
1357
|
+
"modal.form.code.label": "Entrez le code à 6 chiffres de l'application d'authentification",
|
|
1358
|
+
"modal.form.code.validation_attribute": "code",
|
|
1359
|
+
"modal.form.code.below_content": "Vous devrez entrer le code à 6 chiffres de votre application d'authentification à chaque fois que vous vous connecterez ou effectuerez des actions sensibles.",
|
|
1360
|
+
"modal.form.code.messages.invalid": "Le code que vous avez entré est invalide.",
|
|
1361
|
+
"modal.actions.submit.label": "Activer l'application d'authentification",
|
|
1362
|
+
"notifications.enabled.title": "L'application d'authentification a été activée"
|
|
1265
1363
|
},
|
|
1266
1364
|
"auth/multi-factor/app/provider": {
|
|
1267
1365
|
"management_schema.actions.label": "Application d'authentification",
|
|
@@ -1356,7 +1454,12 @@
|
|
|
1356
1454
|
"notifications.email_change_verification_sent.title": "Demande de modification de l'adresse email envoyée",
|
|
1357
1455
|
"notifications.email_change_verification_sent.body": "Une demande de modification de votre adresse email a été envoyée à :email. Veuillez vérifier votre email pour vérifier la modification.",
|
|
1358
1456
|
"notifications.saved.title": "Sauvegardé",
|
|
1359
|
-
"actions.cancel.label": "Annuler"
|
|
1457
|
+
"actions.cancel.label": "Annuler",
|
|
1458
|
+
"sections.information.heading": "Informations du profil",
|
|
1459
|
+
"sections.information.description": "Votre nom et l'adresse e-mail avec laquelle vous vous connectez.",
|
|
1460
|
+
"sections.password.heading": "Mot de passe",
|
|
1461
|
+
"sections.password.description": "Utilisez un mot de passe long et aléatoire pour sécuriser votre compte.",
|
|
1462
|
+
"multi_factor_authentication.description": "Une seconde étape après le mot de passe : un code d'application, un code par e-mail ou une clé de sécurité."
|
|
1360
1463
|
},
|
|
1361
1464
|
"auth/pages/email-verification/email-verification-prompt": {
|
|
1362
1465
|
"title": "Vérifier votre adresse email",
|
|
@@ -1493,6 +1596,77 @@
|
|
|
1493
1596
|
"widgets/filament-info-widget": {
|
|
1494
1597
|
"actions.open_documentation.label": "Documentation",
|
|
1495
1598
|
"actions.open_github.label": "GitHub"
|
|
1599
|
+
},
|
|
1600
|
+
"auth/multi-factor/security-keys/provider": {
|
|
1601
|
+
"login_form.label": "Utiliser une clé de sécurité",
|
|
1602
|
+
"login_form.credential.label": "Clé de sécurité",
|
|
1603
|
+
"login_form.credential.validation_attribute": "clé de sécurité",
|
|
1604
|
+
"login_form.credential.messages.invalid": "La clé de sécurité n'a pas pu être vérifiée.",
|
|
1605
|
+
"management_schema.actions.label": "Clés de sécurité",
|
|
1606
|
+
"management_schema.actions.below_content": "Utilisez une clé de sécurité physique ou une clé d'accès enregistrée sur votre appareil pour vérifier votre identité.",
|
|
1607
|
+
"management_schema.actions.messages.enabled": "Activées",
|
|
1608
|
+
"management_schema.actions.messages.disabled": "Désactivées",
|
|
1609
|
+
"management_schema.actions.messages.added": "Ajoutée le :date",
|
|
1610
|
+
"management_schema.actions.messages.last_used": "Utilisée le :date"
|
|
1611
|
+
},
|
|
1612
|
+
"auth/multi-factor/security-keys/actions/register": {
|
|
1613
|
+
"label": "Ajouter une clé de sécurité",
|
|
1614
|
+
"modal.heading": "Ajouter une clé de sécurité",
|
|
1615
|
+
"modal.description": "Donnez un nom à la clé, puis suivez les instructions de votre navigateur.",
|
|
1616
|
+
"modal.form.name.label": "Nom",
|
|
1617
|
+
"modal.form.name.placeholder": "Ma clé de sécurité",
|
|
1618
|
+
"modal.form.credential.label": "Clé de sécurité",
|
|
1619
|
+
"modal.form.credential.validation_attribute": "clé de sécurité",
|
|
1620
|
+
"modal.form.credential.messages.invalid": "La clé de sécurité n'a pas pu être enregistrée. Réessayez.",
|
|
1621
|
+
"modal.form.credential.messages.rate_limited": "Trop de tentatives. Veuillez réessayer plus tard.",
|
|
1622
|
+
"modal.form.password.label": "Mot de passe actuel",
|
|
1623
|
+
"modal.form.password.validation_attribute": "mot de passe actuel",
|
|
1624
|
+
"modal.actions.submit.label": "Ajouter la clé",
|
|
1625
|
+
"notifications.registered.title": "Clé de sécurité ajoutée"
|
|
1626
|
+
},
|
|
1627
|
+
"auth/multi-factor/security-keys/actions/remove": {
|
|
1628
|
+
"label": "Retirer une clé",
|
|
1629
|
+
"modal.heading": "Retirer une clé de sécurité",
|
|
1630
|
+
"modal.description": "La clé ne sera plus acceptée pour se connecter.",
|
|
1631
|
+
"modal.form.key.label": "Clé",
|
|
1632
|
+
"modal.form.password.label": "Mot de passe actuel",
|
|
1633
|
+
"modal.form.password.validation_attribute": "mot de passe actuel",
|
|
1634
|
+
"modal.actions.submit.label": "Retirer la clé",
|
|
1635
|
+
"notifications.removed.title": "Clé de sécurité retirée"
|
|
1636
|
+
},
|
|
1637
|
+
"auth/multi-factor/security-keys/field": {
|
|
1638
|
+
"actions.register.label": "Utiliser ma clé de sécurité",
|
|
1639
|
+
"actions.authenticate.label": "Utiliser ma clé de sécurité",
|
|
1640
|
+
"messages.waiting": "Suivez les instructions de votre navigateur…",
|
|
1641
|
+
"messages.registered": "Clé prête : validez le formulaire pour l'ajouter.",
|
|
1642
|
+
"messages.verified": "Clé de sécurité vérifiée.",
|
|
1643
|
+
"messages.cancelled": "L'opération a été annulée ou a expiré.",
|
|
1644
|
+
"messages.unsupported": "Ce navigateur ne prend pas en charge les clés de sécurité.",
|
|
1645
|
+
"messages.failed": "La clé de sécurité n'a pas pu être utilisée. Réessayez."
|
|
1646
|
+
},
|
|
1647
|
+
"errors": {
|
|
1648
|
+
"label": "Erreur :code",
|
|
1649
|
+
"actions.home": "Retour à l’accueil",
|
|
1650
|
+
"actions.back": "Page précédente",
|
|
1651
|
+
"actions.retry": "Réessayer",
|
|
1652
|
+
"actions.login": "Se connecter",
|
|
1653
|
+
"details": "Détails de l’erreur",
|
|
1654
|
+
"401.title": "Connectez-vous pour embarquer",
|
|
1655
|
+
"401.description": "Vous devez être connecté pour ouvrir cette page.",
|
|
1656
|
+
"403.title": "Cette ligne vous est fermée",
|
|
1657
|
+
"403.description": "Vous n’avez pas l’autorisation d’ouvrir cette page. Si vous pensez que c’est une erreur, contactez un administrateur.",
|
|
1658
|
+
"403.invalid_link": "Ce lien est invalide ou a expiré.",
|
|
1659
|
+
"403.email_change_blocked": "Ce changement d’adresse e-mail a été bloqué.",
|
|
1660
|
+
"404.title": "Perdu dans les nuages",
|
|
1661
|
+
"404.description": "La page que vous cherchez n’existe pas ou a été déplacée.",
|
|
1662
|
+
"419.title": "Votre cabine est partie",
|
|
1663
|
+
"419.description": "Cette page a expiré après une longue inactivité. Rechargez-la puis réessayez.",
|
|
1664
|
+
"429.title": "Heure de pointe",
|
|
1665
|
+
"429.description": "Trop de requêtes en peu de temps. Patientez un instant avant de réessayer.",
|
|
1666
|
+
"500.title": "Le câble a lâché",
|
|
1667
|
+
"500.description": "Une erreur est survenue de notre côté. Réessayez dans quelques instants.",
|
|
1668
|
+
"503.title": "Ligne en maintenance",
|
|
1669
|
+
"503.description": "Nous entretenons la ligne. Nous revenons très vite."
|
|
1496
1670
|
}
|
|
1497
1671
|
}
|
|
1498
1672
|
},
|
|
@@ -2087,4 +2261,4 @@
|
|
|
2087
2261
|
}
|
|
2088
2262
|
}
|
|
2089
2263
|
}
|
|
2090
|
-
}
|
|
2264
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<line x1="3.41348" y1="3.0456" x2="17.0456" y2="17.5865" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
|
3
|
+
<path d="M9.70948 13.2891L6.58057 16.4189C6.19757 16.8021 5.74077 17.1034 5.2378 17.3047L2.08253 18.5674C1.99181 18.6036 1.89208 18.6124 1.79639 18.5928C1.70063 18.5731 1.6126 18.5252 1.54346 18.4561C1.47439 18.3869 1.42737 18.2989 1.40772 18.2031C1.38808 18.1073 1.39676 18.0078 1.43311 17.917L2.69483 14.7617C2.89583 14.2589 3.19684 13.802 3.5796 13.4189L6.80518 10.1924L9.70948 13.2891ZM15.9995 1.87988C16.562 1.87988 17.1017 2.10331 17.4995 2.50098C17.8973 2.8988 18.1216 3.43838 18.1216 4.00098C18.1216 4.56359 17.8973 5.10315 17.4995 5.50098L12.8315 10.168L9.92823 7.07031L14.4995 2.50098C14.8972 2.10327 15.4371 1.88001 15.9995 1.87988Z" fill="currentColor"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6l16 0" />
|
|
3
|
+
<path d="M8 12l8 0" />
|
|
4
|
+
<path d="M6 18l12 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6l16 0" />
|
|
3
|
+
<path d="M10 12l10 0" />
|
|
4
|
+
<path d="M6 18l14 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6l16 0" />
|
|
3
|
+
<path d="M4 12l16 0" />
|
|
4
|
+
<path d="M4 18l12 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6l16 0" />
|
|
3
|
+
<path d="M4 12l10 0" />
|
|
4
|
+
<path d="M4 18l14 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M17 15l4 4m0 -4l-4 4" />
|
|
3
|
+
<path d="M7 6v-1h11v1" />
|
|
4
|
+
<path d="M7 19l4 0" />
|
|
5
|
+
<path d="M13 5l-4 14" />
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M14.5 4h2.5a3 3 0 0 1 3 3v10a3 3 0 0 1 -3 3h-10a3 3 0 0 1 -3 -3v-5" />
|
|
3
|
+
<path d="M6 5l-2 2l2 2" />
|
|
4
|
+
<path d="M10 9l2 -2l-2 -2" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M7 8l-4 4l4 4" />
|
|
3
|
+
<path d="M17 8l4 4l-4 4" />
|
|
4
|
+
<path d="M14 4l-4 16" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6h2" />
|
|
3
|
+
<path d="M4 10h5.5" />
|
|
4
|
+
<path d="M4 14h5.5" />
|
|
5
|
+
<path d="M4 18h5.5" />
|
|
6
|
+
<path d="M14.5 6h5.5" />
|
|
7
|
+
<path d="M14.5 10h5.5" />
|
|
8
|
+
<path d="M18 14h2" />
|
|
9
|
+
<path d="M14.5 18h3.5" />
|
|
10
|
+
<path d="M3 3l18 18" />
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 6l5.5 0" />
|
|
3
|
+
<path d="M4 10l5.5 0" />
|
|
4
|
+
<path d="M4 14l5.5 0" />
|
|
5
|
+
<path d="M4 18l5.5 0" />
|
|
6
|
+
<path d="M14.5 6l5.5 0" />
|
|
7
|
+
<path d="M14.5 10l5.5 0" />
|
|
8
|
+
<path d="M14.5 14l5.5 0" />
|
|
9
|
+
<path d="M14.5 18l5.5 0" />
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 18v-12a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z" />
|
|
3
|
+
<path d="M4 9h16" />
|
|
4
|
+
<path d="M10 14l2 2l2 -2" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M19 18v-8l-2 2" />
|
|
4
|
+
<path d="M4 6v12" />
|
|
5
|
+
<path d="M12 6v12" />
|
|
6
|
+
<path d="M11 18h2" />
|
|
7
|
+
<path d="M3 18h2" />
|
|
8
|
+
<path d="M4 12h8" />
|
|
9
|
+
<path d="M3 6h2" />
|
|
10
|
+
<path d="M11 6h2" />
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M17 12a2 2 0 1 1 4 0c0 .591 -.417 1.318 -.816 1.858l-3.184 4.143l4 0" />
|
|
4
|
+
<path d="M4 6v12" />
|
|
5
|
+
<path d="M12 6v12" />
|
|
6
|
+
<path d="M11 18h2" />
|
|
7
|
+
<path d="M3 18h2" />
|
|
8
|
+
<path d="M4 12h8" />
|
|
9
|
+
<path d="M3 6h2" />
|
|
10
|
+
<path d="M11 6h2" />
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M19 14a2 2 0 1 0 -2 -2" />
|
|
4
|
+
<path d="M17 16a2 2 0 1 0 2 -2" />
|
|
5
|
+
<path d="M4 6v12" />
|
|
6
|
+
<path d="M12 6v12" />
|
|
7
|
+
<path d="M11 18h2" />
|
|
8
|
+
<path d="M3 18h2" />
|
|
9
|
+
<path d="M4 12h8" />
|
|
10
|
+
<path d="M3 6h2" />
|
|
11
|
+
<path d="M11 6h2" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M20 18v-8l-4 6h5" />
|
|
4
|
+
<path d="M4 6v12" />
|
|
5
|
+
<path d="M12 6v12" />
|
|
6
|
+
<path d="M11 18h2" />
|
|
7
|
+
<path d="M3 18h2" />
|
|
8
|
+
<path d="M4 12h8" />
|
|
9
|
+
<path d="M3 6h2" />
|
|
10
|
+
<path d="M11 6h2" />
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M17 18h2a2 2 0 1 0 0 -4h-2v-4h4" />
|
|
4
|
+
<path d="M4 6v12" />
|
|
5
|
+
<path d="M12 6v12" />
|
|
6
|
+
<path d="M11 18h2" />
|
|
7
|
+
<path d="M3 18h2" />
|
|
8
|
+
<path d="M4 12h8" />
|
|
9
|
+
<path d="M3 6h2" />
|
|
10
|
+
<path d="M11 6h2" />
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M19 14a2 2 0 1 0 0 4a2 2 0 0 0 0 -4" />
|
|
4
|
+
<path d="M21 12a2 2 0 1 0 -4 0v4" />
|
|
5
|
+
<path d="M4 6v12" />
|
|
6
|
+
<path d="M12 6v12" />
|
|
7
|
+
<path d="M11 18h2" />
|
|
8
|
+
<path d="M3 18h2" />
|
|
9
|
+
<path d="M4 12h8" />
|
|
10
|
+
<path d="M3 6h2" />
|
|
11
|
+
<path d="M11 6h2" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M7 12h10" />
|
|
3
|
+
<path d="M7 5v14" />
|
|
4
|
+
<path d="M17 5v14" />
|
|
5
|
+
<path d="M15 19h4" />
|
|
6
|
+
<path d="M15 5h4" />
|
|
7
|
+
<path d="M5 19h4" />
|
|
8
|
+
<path d="M5 5h4" />
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M3 19h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" />
|
|
3
|
+
<path d="M12.5 5.5l4 4" />
|
|
4
|
+
<path d="M4.5 13.5l4 4" />
|
|
5
|
+
<path d="M21 15v4h-8l4 -4z" />
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 19v-10.5a3.5 3.5 0 1 1 7 0v10.5" />
|
|
3
|
+
<path d="M4 13h7" />
|
|
4
|
+
<path d="M18 9v6" />
|
|
5
|
+
<path d="M21 12h-6" />
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
3
|
+
<path d="M9 12h6" />
|
|
4
|
+
<path d="M12 9v6" />
|
|
5
|
+
<path d="M6 19a2 2 0 0 1 -2 -2v-4l-1 -1l1 -1v-4a2 2 0 0 1 2 -2" />
|
|
6
|
+
<path d="M18 19a2 2 0 0 0 2 -2v-4l1 -1l-1 -1v-4a2 2 0 0 0 -2 -2" />
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M13 4v16" />
|
|
3
|
+
<path d="M17 4v16" />
|
|
4
|
+
<path d="M19 4h-9.5a4.5 4.5 0 0 0 0 9h3.5" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 19v-10.5a3.5 3.5 0 1 1 7 0v10.5" />
|
|
3
|
+
<path d="M4 13h7" />
|
|
4
|
+
<path d="M21 12h-6" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M5 7l8 10m-8 0l8 -10" />
|
|
4
|
+
<path d="M21 20h-4l3.5 -4a1.73 1.73 0 0 0 -3.5 -2" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
3
|
+
<path d="M5 7l8 10m-8 0l8 -10" />
|
|
4
|
+
<path d="M21 11h-4l3.5 -4a1.73 1.73 0 0 0 -3.5 -2" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M6 4h4a1 1 0 0 1 1 1v14a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1v-14a1 1 0 0 1 1 -1z" />
|
|
3
|
+
<path d="M15 12l4 0" />
|
|
4
|
+
<path d="M17 10l0 4" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M14 4h4a1 1 0 0 1 1 1v14a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1v-14a1 1 0 0 1 1 -1z"/>
|
|
3
|
+
<path d="M5 12l4 0"/>
|
|
4
|
+
<path d="M7 10l0 4"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M20 6v4a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h14a1 1 0 0 1 1 1z" />
|
|
3
|
+
<path d="M12 15l0 4" />
|
|
4
|
+
<path d="M14 17l-4 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M4 18v-4a1 1 0 0 1 1 -1h14a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1z" />
|
|
3
|
+
<path d="M12 9v-4" />
|
|
4
|
+
<path d="M10 7l4 0" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M6 4h4a1 1 0 0 1 1 1v14a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1v-14a1 1 0 0 1 1 -1z" />
|
|
3
|
+
<path d="M16 10l4 4" />
|
|
4
|
+
<path d="M16 14l4 -4" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M20 6v4a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h14a1 1 0 0 1 1 1z" />
|
|
3
|
+
<path d="M10 16l4 4" />
|
|
4
|
+
<path d="M10 20l4 -4" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M7 3h12a2 2 0 0 1 2 2v12m-.585 3.413a1.994 1.994 0 0 1 -1.415 .587h-14a2 2 0 0 1 -2 -2v-14c0 -.55 .223 -1.05 .583 -1.412"/>
|
|
3
|
+
<path d="M3 10h7m4 0h7"/>
|
|
4
|
+
<path d="M10 3v3m0 4v11"/>
|
|
5
|
+
<path d="M3 3l18 18"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M12 21v-6"/>
|
|
3
|
+
<path d="M12 9V3"/>
|
|
4
|
+
<path d="M3 15h18"/>
|
|
5
|
+
<path d="M3 9h18"/>
|
|
6
|
+
<rect width="18" height="18" x="3" y="3" rx="2"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M12 15V9"/>
|
|
3
|
+
<path d="M3 15h18"/>
|
|
4
|
+
<path d="M3 9h18"/>
|
|
5
|
+
<rect width="18" height="18" x="3" y="3" rx="2"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"/>
|
|
3
|
+
<path d="m16 19 2 2 4-4"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<rect width="18" height="18" x="3" y="3" rx="2"/>
|
|
3
|
+
<path d="M14 9h1"/>
|
|
4
|
+
<path d="M19 9h2"/>
|
|
5
|
+
<path d="M3 9h2"/>
|
|
6
|
+
<path d="M9 9h1"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-slot="icon">
|
|
2
|
+
<path d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14z"/>
|
|
3
|
+
<path d="M3 10h18"/>
|
|
4
|
+
<path d="M10 3v18"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Rewrites component tags to EJS. Templates without `<x-` are returned unchanged. */
|
|
2
|
+
export declare function compileComponentTags(source: string, file?: string): string;
|
|
3
|
+
/** Attribute names that go to the component's attribute bag instead of its props (HTML, Alpine and Livewire attributes). */
|
|
4
|
+
export declare const isHtmlAttribute: (name: string) => boolean;
|
|
5
|
+
/** `icon-position` → `iconPosition`. */
|
|
6
|
+
export declare const camel: (name: string) => string;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Component tags in EJS views: `<x-name …>…</x-name>`, `<x-name … />` and named slots (`<x-slot name="footer">` or `<x-slot:footer>`),
|
|
2
|
+
// compiled to plain EJS before the template itself is compiled.
|
|
3
|
+
//
|
|
4
|
+
// A component's content is captured from the template's output buffer (`__output`, EJS's own variable): the
|
|
5
|
+
// generated code remembers where the content starts, cuts it out once it is rendered, and passes it as the slot.
|
|
6
|
+
const NAME = /^[A-Za-z0-9_.:-]+/;
|
|
7
|
+
/** Escapes a string for a JavaScript string literal placed inside an EJS tag. */
|
|
8
|
+
const literal = (value) => JSON.stringify(value).replace(/%>/g, '%\\x3e');
|
|
9
|
+
function parseAttributes(source, tag) {
|
|
10
|
+
const attributes = [];
|
|
11
|
+
let rest = source.trim();
|
|
12
|
+
while (rest) {
|
|
13
|
+
const match = /^(:?)([A-Za-z_@][\w.:@-]*)(?:\s*=\s*("([^"]*)"|'([^']*)'))?/.exec(rest);
|
|
14
|
+
if (!match)
|
|
15
|
+
throw new Error(`Invalid attribute in <x-${tag}>: ${rest.slice(0, 40)}`);
|
|
16
|
+
const [whole, bound, name, quoted, double, single] = match;
|
|
17
|
+
const value = double ?? single ?? '';
|
|
18
|
+
attributes.push({ name, value, kind: bound ? 'expression' : quoted === undefined ? 'flag' : 'string' });
|
|
19
|
+
rest = rest.slice(whole.length).trim();
|
|
20
|
+
}
|
|
21
|
+
return attributes;
|
|
22
|
+
}
|
|
23
|
+
/** JavaScript object literal of a tag's attributes, evaluated in the template's scope. */
|
|
24
|
+
function propsExpression(attributes) {
|
|
25
|
+
return `{ ${attributes.map((attribute) => `${literal(attribute.name)}: ${attribute.kind === 'expression' ? `(${attribute.value})` : attribute.kind === 'flag' ? 'true' : literal(attribute.value)}`).join(', ')} }`;
|
|
26
|
+
}
|
|
27
|
+
/** Finds the `>` that ends a tag, skipping quoted attribute values. */
|
|
28
|
+
function tagEnd(source, from) {
|
|
29
|
+
let quote = null;
|
|
30
|
+
for (let index = from; index < source.length; index++) {
|
|
31
|
+
const char = source[index];
|
|
32
|
+
if (quote) {
|
|
33
|
+
if (char === quote)
|
|
34
|
+
quote = null;
|
|
35
|
+
}
|
|
36
|
+
else if (char === '"' || char === "'")
|
|
37
|
+
quote = char;
|
|
38
|
+
else if (char === '>')
|
|
39
|
+
return index;
|
|
40
|
+
}
|
|
41
|
+
return -1;
|
|
42
|
+
}
|
|
43
|
+
/** Rewrites component tags to EJS. Templates without `<x-` are returned unchanged. */
|
|
44
|
+
export function compileComponentTags(source, file = 'template') {
|
|
45
|
+
if (!source.includes('<x-'))
|
|
46
|
+
return source;
|
|
47
|
+
let out = '<% var __xs = [], __xn = []; %>';
|
|
48
|
+
const open = [];
|
|
49
|
+
let index = 0;
|
|
50
|
+
const capture = '<% __xs.push(__output.length); %>';
|
|
51
|
+
const cut = 'const __s = __output.slice(__xs.pop()); __output = __output.slice(0, __output.length - __s.length);';
|
|
52
|
+
while (index < source.length) {
|
|
53
|
+
const next = source.indexOf('<', index);
|
|
54
|
+
if (next === -1) {
|
|
55
|
+
out += source.slice(index);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
out += source.slice(index, next);
|
|
59
|
+
// EJS tags (code, output, comments) are copied as they are: a tag quoted in a comment is not a component.
|
|
60
|
+
if (source.startsWith('<%', next)) {
|
|
61
|
+
const ejsEnd = source.indexOf('%>', next + 2);
|
|
62
|
+
if (ejsEnd === -1) {
|
|
63
|
+
out += source.slice(next);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
out += source.slice(next, ejsEnd + 2);
|
|
67
|
+
index = ejsEnd + 2;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const closing = source.startsWith('</x-', next);
|
|
71
|
+
if (!closing && !source.startsWith('<x-', next)) {
|
|
72
|
+
out += '<';
|
|
73
|
+
index = next + 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const nameStart = next + (closing ? 4 : 3);
|
|
77
|
+
const name = NAME.exec(source.slice(nameStart))?.[0];
|
|
78
|
+
if (!name) {
|
|
79
|
+
out += '<';
|
|
80
|
+
index = next + 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const end = tagEnd(source, nameStart + name.length);
|
|
84
|
+
if (end === -1)
|
|
85
|
+
throw new Error(`${file}: unclosed tag <x-${name}`);
|
|
86
|
+
const body = source.slice(nameStart + name.length, end);
|
|
87
|
+
index = end + 1;
|
|
88
|
+
if (closing) {
|
|
89
|
+
const current = open.pop();
|
|
90
|
+
const closesSlot = name === 'slot' && current?.name.startsWith('slot');
|
|
91
|
+
if (!current || (current.name !== name && !closesSlot))
|
|
92
|
+
throw new Error(`${file}: </x-${name}> does not close ${current ? `<x-${current.name}>` : 'any tag'}`);
|
|
93
|
+
if (name === 'slot' || name.startsWith('slot:'))
|
|
94
|
+
out += `<% { ${cut} __xn[__xn.length - 1][${current.props}] = __s; } %>`;
|
|
95
|
+
else
|
|
96
|
+
out += `<% { ${cut} const __n = __xn.pop(); %><%- __component(${literal(name)}, ${current.props}, __s, __n) %><% } %>`;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const selfClosing = body.trimEnd().endsWith('/');
|
|
100
|
+
const attributes = parseAttributes(selfClosing ? body.trimEnd().slice(0, -1) : body, name);
|
|
101
|
+
if (name === 'slot' || name.startsWith('slot:')) {
|
|
102
|
+
const slotName = name.startsWith('slot:') ? name.slice(5) : attributes.find((attribute) => attribute.name === 'name')?.value;
|
|
103
|
+
if (!slotName)
|
|
104
|
+
throw new Error(`${file}: <x-slot> needs a name`);
|
|
105
|
+
if (!open.length)
|
|
106
|
+
throw new Error(`${file}: <x-slot name="${slotName}"> must be inside a component`);
|
|
107
|
+
if (selfClosing) {
|
|
108
|
+
out += `<% __xn[__xn.length - 1][${literal(slotName)}] = ''; %>`;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
open.push({ name, props: literal(slotName) });
|
|
112
|
+
out += capture;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const props = propsExpression(attributes);
|
|
116
|
+
if (selfClosing) {
|
|
117
|
+
out += `<%- __component(${literal(name)}, ${props}, '', {}) %>`;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
open.push({ name, props });
|
|
121
|
+
out += `<% __xn.push({}); %>${capture}`;
|
|
122
|
+
}
|
|
123
|
+
if (open.length)
|
|
124
|
+
throw new Error(`${file}: <x-${open[open.length - 1].name}> is never closed`);
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
/** Attribute names that go to the component's attribute bag instead of its props (HTML, Alpine and Livewire attributes). */
|
|
128
|
+
export const isHtmlAttribute = (name) => /^(class|style|id)$/.test(name) || /^(x-|data-|aria-|wire:|@)/.test(name) || name.includes(':');
|
|
129
|
+
/** `icon-position` → `iconPosition`. */
|
|
130
|
+
export const camel = (name) => name.replace(/-([a-z0-9])/g, (_match, char) => char.toUpperCase());
|
package/lib/index.d.ts
CHANGED
|
@@ -119,18 +119,42 @@ export declare function icon(name: string, options?: {
|
|
|
119
119
|
export declare function registerIcon(name: string, svg: string): void;
|
|
120
120
|
/** Loading spinner SVG. */
|
|
121
121
|
export declare function loadingIndicator(attributes?: Attributes, size?: string): string;
|
|
122
|
-
/**
|
|
122
|
+
/** Renders a component from its props (camelCased, named slots included), its attribute bag and its default slot (HTML). */
|
|
123
|
+
export type ComponentRenderer = (props: Record<string, any> & {
|
|
124
|
+
attributes: Record<string, any>;
|
|
125
|
+
}, slot: string) => string;
|
|
126
|
+
/**
|
|
127
|
+
* View registry: `filament-forms::components.text-input` resolves to an EJS file; override directories are checked first.
|
|
128
|
+
* Views may use component tags (`<x-section heading="Orders">…</x-section>`): built-in components, components registered with
|
|
129
|
+
* `component()`, and EJS files of the directories given to `components()`.
|
|
130
|
+
*/
|
|
123
131
|
export declare class ViewRegistry {
|
|
124
132
|
private namespaces;
|
|
125
133
|
private overrides;
|
|
126
134
|
private compiled;
|
|
127
135
|
private shared;
|
|
136
|
+
private componentRenderers;
|
|
137
|
+
private componentDirectories;
|
|
138
|
+
/** Registers a component rendered by a function: `<x-name>` in any view. Registering an existing name replaces it. */
|
|
139
|
+
component(name: string, renderer: ComponentRenderer): this;
|
|
140
|
+
/**
|
|
141
|
+
* Directory of EJS components: `<x-card>` renders `<dir>/card.ejs`, `<x-forms.field>` renders `<dir>/forms/field.ejs`.
|
|
142
|
+
* The view receives its props, `slot` (the content, already rendered), `slots` (named slots) and `attributes` (HTML attributes).
|
|
143
|
+
* Directories registered later win, and files win over components registered with `component()`.
|
|
144
|
+
*/
|
|
145
|
+
components(directory: string | URL): this;
|
|
146
|
+
hasComponent(name: string): boolean;
|
|
147
|
+
private componentFile;
|
|
148
|
+
/** Renders a component tag. HTML, Alpine and Livewire attributes go to the attribute bag; the others become camelCased props. */
|
|
149
|
+
renderComponent(name: string, raw: Record<string, unknown>, slot?: string, slots?: Record<string, string>): string;
|
|
128
150
|
namespace(name: string, dir: string): this;
|
|
129
151
|
/** Application override directory: `<dir>/<namespace>/<path>.ejs` replaces the package view. */
|
|
130
152
|
overrideFrom(dir: string): this;
|
|
131
153
|
share(data: Record<string, unknown>): this;
|
|
132
154
|
resolve(view: string): string;
|
|
133
155
|
render(view: string, data?: Record<string, unknown>): string;
|
|
156
|
+
/** Renders an EJS file directly (component files, page views given by path). */
|
|
157
|
+
renderFile(file: string, data?: Record<string, unknown>, cacheKey?: string): string;
|
|
134
158
|
}
|
|
135
159
|
export declare const views: ViewRegistry;
|
|
136
160
|
/** Registers a callback applied to every instance of the class (and its subclasses) created afterwards by `make()`. */
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { camel, compileComponentTags, isHtmlAttribute } from "./components.js";
|
|
2
3
|
// @navette-js/support — shared building blocks: escaping, attribute bags, JS serialization, lazy evaluation, colors, icons,
|
|
3
4
|
// namespaced EJS views.
|
|
4
5
|
import ejs from 'ejs';
|
|
@@ -412,13 +413,68 @@ export function loadingIndicator(attributes = new Attributes(), size = 'md') {
|
|
|
412
413
|
const a = attributes.class(['fi-icon fi-loading-indicator', `fi-size-${size}`]);
|
|
413
414
|
return `<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" ${a.toHtml()}><path clip-rule="evenodd" d="M12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill-rule="evenodd" fill="currentColor" opacity="0.2"></path><path d="M2 12C2 6.47715 6.47715 2 12 2V5C8.13401 5 5 8.13401 5 12H2Z" fill="currentColor"></path></svg>`;
|
|
414
415
|
}
|
|
415
|
-
|
|
416
|
-
|
|
416
|
+
/**
|
|
417
|
+
* View registry: `filament-forms::components.text-input` resolves to an EJS file; override directories are checked first.
|
|
418
|
+
* Views may use component tags (`<x-section heading="Orders">…</x-section>`): built-in components, components registered with
|
|
419
|
+
* `component()`, and EJS files of the directories given to `components()`.
|
|
420
|
+
*/
|
|
417
421
|
export class ViewRegistry {
|
|
418
422
|
namespaces = new Map();
|
|
419
423
|
overrides = [];
|
|
420
424
|
compiled = new Map();
|
|
421
425
|
shared = {};
|
|
426
|
+
componentRenderers = new Map();
|
|
427
|
+
componentDirectories = [];
|
|
428
|
+
/** Registers a component rendered by a function: `<x-name>` in any view. Registering an existing name replaces it. */
|
|
429
|
+
component(name, renderer) {
|
|
430
|
+
if (!/^[A-Za-z0-9_.-]+$/.test(name))
|
|
431
|
+
throw new Error(`Invalid component name: ${name}`);
|
|
432
|
+
this.componentRenderers.set(name, renderer);
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Directory of EJS components: `<x-card>` renders `<dir>/card.ejs`, `<x-forms.field>` renders `<dir>/forms/field.ejs`.
|
|
437
|
+
* The view receives its props, `slot` (the content, already rendered), `slots` (named slots) and `attributes` (HTML attributes).
|
|
438
|
+
* Directories registered later win, and files win over components registered with `component()`.
|
|
439
|
+
*/
|
|
440
|
+
components(directory) {
|
|
441
|
+
this.componentDirectories.unshift(directory instanceof URL ? fileURLToPath(directory) : directory);
|
|
442
|
+
return this;
|
|
443
|
+
}
|
|
444
|
+
hasComponent(name) { return this.componentRenderers.has(name) || this.componentFile(name) !== null; }
|
|
445
|
+
componentFile(name) {
|
|
446
|
+
if (!/^[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*$/.test(name))
|
|
447
|
+
return null;
|
|
448
|
+
for (const dir of this.componentDirectories) {
|
|
449
|
+
const file = path.join(dir, ...name.split('.')) + '.ejs';
|
|
450
|
+
if (existsSync(file))
|
|
451
|
+
return file;
|
|
452
|
+
}
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
/** Renders a component tag. HTML, Alpine and Livewire attributes go to the attribute bag; the others become camelCased props. */
|
|
456
|
+
renderComponent(name, raw, slot = '', slots = {}) {
|
|
457
|
+
const props = {};
|
|
458
|
+
const attributes = {};
|
|
459
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
460
|
+
if (isHtmlAttribute(key))
|
|
461
|
+
attributes[key] = value;
|
|
462
|
+
else
|
|
463
|
+
props[camel(key)] = value;
|
|
464
|
+
}
|
|
465
|
+
// A slot made of whitespace only (line breaks around named slots) counts as empty.
|
|
466
|
+
for (const [key, value] of Object.entries(slots))
|
|
467
|
+
props[camel(key)] = value.trim() === '' ? '' : value;
|
|
468
|
+
if (slot.trim() === '')
|
|
469
|
+
slot = '';
|
|
470
|
+
const file = this.componentFile(name);
|
|
471
|
+
if (file)
|
|
472
|
+
return this.renderFile(file, { ...props, slot, slots, attributes: new Attributes(attributes) });
|
|
473
|
+
const renderer = this.componentRenderers.get(name);
|
|
474
|
+
if (!renderer)
|
|
475
|
+
throw new Error(`Unknown component <x-${name}>: register it with views.component() or views.components(directory).`);
|
|
476
|
+
return renderer({ ...props, attributes }, slot);
|
|
477
|
+
}
|
|
422
478
|
namespace(name, dir) { this.namespaces.set(name, dir); return this; }
|
|
423
479
|
/** Application override directory: `<dir>/<namespace>/<path>.ejs` replaces the package view. */
|
|
424
480
|
overrideFrom(dir) { this.overrides.unshift(dir); this.compiled.clear(); return this; }
|
|
@@ -436,14 +492,15 @@ export class ViewRegistry {
|
|
|
436
492
|
throw new Error(`Unknown view namespace: ${ns}`);
|
|
437
493
|
return path.join(base, rel);
|
|
438
494
|
}
|
|
439
|
-
render(view, data = {}) {
|
|
440
|
-
|
|
495
|
+
render(view, data = {}) { return this.renderFile(this.resolve(view), data, view); }
|
|
496
|
+
/** Renders an EJS file directly (component files, page views given by path). */
|
|
497
|
+
renderFile(file, data = {}, cacheKey = file) {
|
|
498
|
+
let fn = this.compiled.get(cacheKey);
|
|
441
499
|
if (!fn) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
this.compiled.set(view, fn);
|
|
500
|
+
fn = ejs.compile(compileComponentTags(readFileSync(file, 'utf8'), file), { filename: file });
|
|
501
|
+
this.compiled.set(cacheKey, fn);
|
|
445
502
|
}
|
|
446
|
-
return fn({ e, js, cls, attrs, icon, loadingIndicator, view: (v, d) => this.render(v, d), ...this.shared, ...data });
|
|
503
|
+
return fn({ e, js, cls, attrs, icon, loadingIndicator, view: (v, d) => this.render(v, d), __component: (name, props, slot, slots) => this.renderComponent(name, props, slot, slots), ...this.shared, ...data });
|
|
447
504
|
}
|
|
448
505
|
}
|
|
449
506
|
export const views = new ViewRegistry();
|
package/lib/ui.d.ts
CHANGED
|
@@ -196,6 +196,8 @@ export type DropdownItem = {
|
|
|
196
196
|
href?: string | null;
|
|
197
197
|
disabled?: boolean;
|
|
198
198
|
attributes?: Attrs;
|
|
199
|
+
/** Label as HTML already escaped (the content of a `<x-dropdown-item>` tag), used instead of `label`. */
|
|
200
|
+
labelHtml?: string | null;
|
|
199
201
|
};
|
|
200
202
|
/** Dropdown menu item. */
|
|
201
203
|
export declare function dropdownItem(item: DropdownItem): string;
|
package/lib/ui.js
CHANGED
|
@@ -211,7 +211,7 @@ export function dropdownItem(item) {
|
|
|
211
211
|
const iconColor = item.iconColor ?? (color !== 'gray' ? color : null);
|
|
212
212
|
const lead = item.icon ? icon(item.icon, { attributes: new Attributes().class(colorMark(iconColor)) }) : item.image ? `<div class="fi-dropdown-list-item-image" style="background-image: url('${e(item.image)}')"></div>` : '';
|
|
213
213
|
const badgeHtml = item.badge !== null && item.badge !== undefined ? `<span class="${cls([...colorsOf('badge', item.badgeColor ?? 'primary'), 'fi-badge'])}">${e(String(item.badge))}</span>` : '';
|
|
214
|
-
return `<${tag} ${attributes.toHtml()}>${lead}<span class="fi-dropdown-list-item-label">${e(item.label)}</span>${badgeHtml}</${tag}>`;
|
|
214
|
+
return `<${tag} ${attributes.toHtml()}>${lead}<span class="fi-dropdown-list-item-label">${item.labelHtml ?? e(item.label)}</span>${badgeHtml}</${tag}>`;
|
|
215
215
|
}
|
|
216
216
|
/** List of dropdown menu items. */
|
|
217
217
|
export function dropdownList(items) { return `<div class="fi-dropdown-list">${items.map(dropdownItem).join('')}</div>`; }
|
|
@@ -250,5 +250,36 @@ export function modal(props, slot = '') {
|
|
|
250
250
|
.class(['fi-modal', { 'fi-absolute-positioning-context': !props.slideOver, 'fi-modal-slide-over': props.slideOver === true, 'fi-modal-has-sticky-header': props.stickyHeader === true, 'fi-modal-has-sticky-footer': props.stickyFooter === true }]);
|
|
251
251
|
return `<div ${outer.toHtml()}><div aria-hidden="true" x-show="isOpen" x-transition.duration.300ms.opacity class="fi-modal-close-overlay"></div><div${trapOnWindow ? '' : ' tabindex="-1"'}${closeByClickingAway ? ` x-on:click.self="${e(close)}"` : ''}${trapOnWindow ? '' : ' x-trap.noreturn="isTrapActive"'} class="${cls(['fi-modal-window-ctn', { 'fi-clickable': closeByClickingAway }])}"><div${closeByEscaping ? ` x-on:keydown.window.escape="if (isTopmost()) ${e(close)}"` : ''} x-show="isWindowVisible" x-transition:enter="fi-transition-enter" x-transition:leave="fi-transition-leave" x-transition:enter-start="fi-transition-enter-start" x-transition:enter-end="fi-transition-enter-end" x-transition:leave-start="fi-transition-leave-start" x-transition:leave-end="fi-transition-leave-end" wire:key="${e(key('window'))}"${trapOnWindow ? ' x-trap.noreturn="isTrapActive" tabindex="0"' : ''} class="${windowClasses}">${header}${content}${footer}</div></div></div>`;
|
|
252
252
|
}
|
|
253
|
+
// ------------------------------------------------------------------ component tags
|
|
254
|
+
// Built-in components for EJS views: `<x-button color="danger">Delete</x-button>`, `<x-section heading="Orders">…</x-section>`.
|
|
255
|
+
// The default slot is HTML already rendered by the template; props from `name="text"` are plain strings and are escaped by the components.
|
|
256
|
+
const withSlot = (render) => (props, slot) => render(props, slot);
|
|
257
|
+
views
|
|
258
|
+
.component('avatar', (props) => avatar(props))
|
|
259
|
+
// A badge rendered as a link takes its `href` from the tag.
|
|
260
|
+
.component('badge', (props, slot) => badge({ ...props, attributes: { ...props.attributes, href: props.href ?? props.attributes?.href } }, slot))
|
|
261
|
+
.component('breadcrumbs', (props) => breadcrumbs(props.items ?? [], props.label))
|
|
262
|
+
.component('button', withSlot(button))
|
|
263
|
+
.component('callout', (props, slot) => callout({ ...props, footer: props.footer ?? (slot || null) }))
|
|
264
|
+
// Every prop other than `checked` and `valid` is an attribute of the input (`name`, `value`, `disabled`…).
|
|
265
|
+
.component('checkbox', ({ checked, valid, attributes, ...rest }) => checkbox({ checked, valid, attributes: { ...rest, ...attributes } }))
|
|
266
|
+
.component('dropdown', withSlot(dropdown))
|
|
267
|
+
.component('dropdown-list', (props, slot) => (props.items ? dropdownList(props.items) : `<div class="fi-dropdown-list">${slot}</div>`))
|
|
268
|
+
.component('dropdown-item', (props, slot) => dropdownItem({ ...props, label: props.label ?? '', labelHtml: props.label === undefined ? slot.trim() : null }))
|
|
269
|
+
.component('empty-state', (props, slot) => emptyState({ ...props, footer: props.footer ?? (slot || null) }))
|
|
270
|
+
.component('fieldset', withSlot(fieldset))
|
|
271
|
+
.component('icon', (props) => icon(props.name ?? props.icon, { size: props.size, attributes: new Attributes(props.attributes) }))
|
|
272
|
+
.component('icon-button', (props) => iconButton(props))
|
|
273
|
+
.component('input', (props) => input({ ...props.attributes, ...Object.fromEntries(Object.entries(props).filter(([key]) => key !== 'attributes')) }))
|
|
274
|
+
.component('input-wrapper', withSlot(inputWrapper))
|
|
275
|
+
.component('link', withSlot(link))
|
|
276
|
+
.component('loading-indicator', (props) => loadingIndicator(new Attributes(props.attributes), props.size))
|
|
277
|
+
// `id` is an HTML attribute name, so it lands in the attribute bag: these two components need it as a prop.
|
|
278
|
+
.component('modal', (props, slot) => modal({ ...props, id: props.id ?? props.attributes?.id }, slot))
|
|
279
|
+
.component('pagination', (props) => pagination({ ...props, id: props.id ?? props.attributes?.id }))
|
|
280
|
+
.component('section', withSlot(section))
|
|
281
|
+
.component('select', (props, slot) => select({ ...props.attributes, ...Object.fromEntries(Object.entries(props).filter(([key]) => key !== 'attributes')) }, slot))
|
|
282
|
+
.component('spinner', (props) => spinner(props.attributes))
|
|
283
|
+
.component('tabs', (props) => tabs(props, props.items ?? []));
|
|
253
284
|
export const ui = { avatar, badge, breadcrumbs, button, callout, checkbox, dropdown, dropdownItem, dropdownList, emptyState, fieldset, iconButton, input, inputWrapper, link, modal, pagination, section, select, spinner, tabs };
|
|
254
285
|
export { cls, e, js, loadingIndicator };
|