@supersoniks/concorde 3.2.5 → 3.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +131 -124
- package/concorde-core.es.js +808 -716
- package/dist/concorde-core.bundle.js +131 -124
- package/dist/concorde-core.es.js +808 -716
- package/docs/assets/index-C0K6xugr.css +1 -0
- package/docs/assets/index-Dgl1lJQo.js +4861 -0
- package/docs/css/docs.css +0 -0
- package/docs/fonts/ClashGrotesk-Bold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Bold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.eot +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Light.eot +0 -0
- package/docs/fonts/ClashGrotesk-Light.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Medium.eot +0 -0
- package/docs/fonts/ClashGrotesk-Medium.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Regular.eot +0 -0
- package/docs/fonts/ClashGrotesk-Regular.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Variable.eot +0 -0
- package/docs/fonts/ClashGrotesk-Variable.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff2 +0 -0
- package/docs/img/concorde-icon.svg +5 -0
- package/docs/img/concorde-logo.svg +1 -0
- package/docs/img/concorde.png +0 -0
- package/docs/img/concorde_def.png +0 -0
- package/docs/img/concorde_seuil.png.webp +0 -0
- package/docs/img/concorde_seuil_invert.png +0 -0
- package/docs/img/paul_metrand.jpg +0 -0
- package/docs/img/paul_metrand_xs.jpg +0 -0
- package/docs/index.html +93 -0
- package/docs/src/core/components/functional/date/date.md +290 -0
- package/docs/src/core/components/functional/fetch/fetch.md +117 -0
- package/docs/src/core/components/functional/if/if.md +16 -0
- package/docs/src/core/components/functional/list/list.md +199 -0
- package/docs/src/core/components/functional/mix/mix.md +41 -0
- package/docs/src/core/components/functional/queue/queue.md +87 -0
- package/docs/src/core/components/functional/router/router.md +129 -0
- package/docs/src/core/components/functional/sdui/default-library.json +108 -0
- package/docs/src/core/components/functional/sdui/example.json +99 -0
- package/docs/src/core/components/functional/sdui/sdui.md +356 -0
- package/docs/src/core/components/functional/states/states.md +87 -0
- package/docs/src/core/components/functional/submit/submit.md +83 -0
- package/docs/src/core/components/functional/subscriber/subscriber.md +91 -0
- package/docs/src/core/components/functional/value/value.md +35 -0
- package/docs/src/core/components/ui/alert/alert.md +121 -0
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +127 -0
- package/docs/src/core/components/ui/button/button.md +182 -0
- package/docs/src/core/components/ui/captcha/captcha.md +24 -0
- package/docs/src/core/components/ui/card/card.md +97 -0
- package/docs/src/core/components/ui/divider/divider.md +35 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +104 -0
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +129 -0
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +77 -0
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +44 -0
- package/docs/src/core/components/ui/form/input/input.md +167 -0
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +131 -0
- package/docs/src/core/components/ui/form/radio/radio.md +84 -0
- package/docs/src/core/components/ui/form/select/select.md +97 -0
- package/docs/src/core/components/ui/form/switch/switch.md +84 -0
- package/docs/src/core/components/ui/form/textarea/textarea.md +65 -0
- package/docs/src/core/components/ui/group/group.md +75 -0
- package/docs/src/core/components/ui/icon/icon.md +125 -0
- package/docs/src/core/components/ui/icon/icons.json +1 -0
- package/docs/src/core/components/ui/image/image.md +107 -0
- package/docs/src/core/components/ui/link/link.md +43 -0
- package/docs/src/core/components/ui/loader/loader.md +67 -0
- package/docs/src/core/components/ui/menu/menu.md +288 -0
- package/docs/src/core/components/ui/modal/modal.md +123 -0
- package/docs/src/core/components/ui/pop/pop.md +96 -0
- package/docs/src/core/components/ui/progress/progress.md +63 -0
- package/docs/src/core/components/ui/table/table.md +455 -0
- package/docs/src/core/components/ui/tooltip/tooltip.md +82 -0
- package/docs/src/docs/_core-concept/overview.md +57 -0
- package/docs/src/docs/_core-concept/subscriber.md +76 -0
- package/docs/src/docs/_getting-started/concorde-outside.md +143 -0
- package/docs/src/docs/_getting-started/create-a-component.md +137 -0
- package/docs/src/docs/_getting-started/my-first-subscriber.md +174 -0
- package/docs/src/docs/_getting-started/pubsub.md +150 -0
- package/docs/src/docs/_getting-started/start.md +39 -0
- package/docs/src/docs/_getting-started/theming.md +91 -0
- package/docs/src/docs/search/docs-search.json +3917 -0
- package/docs/src/tag-list.json +1 -0
- package/docs/src/tsconfig-model.json +23 -0
- package/docs/src/tsconfig.json +918 -0
- package/docs/svg/regular/plane.svg +1 -0
- package/docs/svg/solid/plane.svg +1 -0
- package/mcp-server/COMPARISON-MCP.md +176 -0
- package/mcp-server/README-MCP-NODEJS.md +284 -0
- package/mcp-server/README-MCP.md +114 -0
- package/mcp-server/README.md +127 -0
- package/mcp-server/TECHNICAL-DOCS.md +269 -0
- package/mcp-server/concorde-mcp-server.js +859 -0
- package/mcp-server/concorde-mcp-server.py +801 -0
- package/mcp-server/cursor-mcp-config-advanced.json +68 -0
- package/mcp-server/cursor-mcp-config-nodejs.json +74 -0
- package/mcp-server/cursor-mcp-config.json +11 -0
- package/mcp-server/install-mcp-nodejs.sh +104 -0
- package/mcp-server/install-mcp.sh +62 -0
- package/mcp-server/package-lock.json +147 -0
- package/mcp-server/package-mcp.json +40 -0
- package/mcp-server/package.json +40 -0
- package/mcp-server/test-mcp.js +107 -0
- package/mcp-server/test-mcp.py +73 -0
- package/package.json +2 -1
- package/php/get-challenge.php +34 -0
- package/php/some-service.php +42 -0
- package/src/core/components/functional/fetch/fetch.md +6 -0
- package/src/core/components/functional/queue/queue.demo.ts +0 -0
- package/src/core/components/functional/sdui/sdui.ts +47 -22
- package/src/core/components/ui/form/checkbox/checkbox.ts +6 -0
- package/src/core/components/ui/form/input-autocomplete/input-autocomplete.ts +9 -1
- package/src/core/components/ui/form/radio/radio.ts +11 -1
- package/src/core/components/ui/icon/icons.ts +0 -0
- package/src/core/components/ui/menu/menu.md +0 -0
- package/src/core/components/ui/modal/modal-close.ts +0 -0
- package/src/core/components/ui/modal/modal.ts +0 -0
- package/src/core/components/ui/toast/toast-item.ts +68 -2
- package/src/core/components/ui/toast/toast.md +166 -0
- package/src/core/components/ui/toast/toast.ts +1 -1
- package/src/core/components/ui/tooltip/tooltip.ts +67 -2
- package/src/core/decorators/Subscriber.ts +0 -0
- package/src/core/mixins/Fetcher.ts +40 -4
- package/src/core/utils/HTML.ts +2 -0
- package/src/core/utils/PublisherProxy.ts +0 -0
- package/src/core/utils/api.ts +7 -0
- package/src/decorators.ts +0 -0
- package/src/docs/navigation/navigation.ts +1 -1
- package/src/docs/search/docs-search.json +135 -0
- package/src/docs.ts +0 -0
- package/src/tsconfig-model.json +0 -0
- package/src/tsconfig.json +0 -0
- package/src/tsconfig.tsbuildinfo +0 -0
- package/templates-test.html +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Script de test pour le serveur MCP Concorde
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# Ajouter le répertoire courant au path
|
|
12
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
13
|
+
|
|
14
|
+
from concorde_mcp_server import ConcordeMCPServer
|
|
15
|
+
|
|
16
|
+
async def test_server():
|
|
17
|
+
"""Teste le serveur MCP"""
|
|
18
|
+
print("🧪 Test du serveur MCP Concorde...")
|
|
19
|
+
|
|
20
|
+
server = ConcordeMCPServer()
|
|
21
|
+
|
|
22
|
+
# Test 1: Vérifier que les composants sont chargés
|
|
23
|
+
print(f"\n📦 Composants chargés: {len(server.components)}")
|
|
24
|
+
for name, comp in list(server.components.items())[:5]:
|
|
25
|
+
print(f" - {comp.tag_name} ({comp.category})")
|
|
26
|
+
|
|
27
|
+
# Test 2: Recherche de composant
|
|
28
|
+
print("\n🔍 Test de recherche...")
|
|
29
|
+
result = await server._search_component("button")
|
|
30
|
+
print(f"Résultat recherche 'button': {len(result.content[0].text)} caractères")
|
|
31
|
+
|
|
32
|
+
# Test 3: Informations sur un composant
|
|
33
|
+
print("\n📋 Test d'informations composant...")
|
|
34
|
+
if "button" in server.components:
|
|
35
|
+
result = await server._get_component_info("button")
|
|
36
|
+
print(f"Info composant 'button': {len(result.content[0].text)} caractères")
|
|
37
|
+
|
|
38
|
+
# Test 4: Génération de code
|
|
39
|
+
print("\n💻 Test de génération de code...")
|
|
40
|
+
if "button" in server.components:
|
|
41
|
+
result = await server._generate_component_code(
|
|
42
|
+
"button",
|
|
43
|
+
{"type": "primary", "size": "lg"},
|
|
44
|
+
"Test"
|
|
45
|
+
)
|
|
46
|
+
print(f"Code généré: {result.content[0].text}")
|
|
47
|
+
|
|
48
|
+
# Test 5: Exemple de formulaire
|
|
49
|
+
print("\n📝 Test d'exemple de formulaire...")
|
|
50
|
+
result = await server._get_form_example([
|
|
51
|
+
{"name": "email", "type": "email", "label": "Email", "required": True},
|
|
52
|
+
{"name": "password", "type": "password", "label": "Mot de passe", "required": True}
|
|
53
|
+
])
|
|
54
|
+
print(f"Formulaire généré: {len(result.content[0].text)} caractères")
|
|
55
|
+
|
|
56
|
+
# Test 6: Informations sur le thème
|
|
57
|
+
print("\n🎨 Test d'informations thème...")
|
|
58
|
+
result = await server._get_theme_info("light")
|
|
59
|
+
print(f"Info thème: {len(result.content[0].text)} caractères")
|
|
60
|
+
|
|
61
|
+
# Test 7: Liste des icônes
|
|
62
|
+
print("\n🔤 Test de liste d'icônes...")
|
|
63
|
+
result = await server._get_icons_list("core")
|
|
64
|
+
print(f"Liste icônes: {len(result.content[0].text)} caractères")
|
|
65
|
+
|
|
66
|
+
print("\n✅ Tous les tests sont passés avec succès !")
|
|
67
|
+
print(f"\n📊 Statistiques:")
|
|
68
|
+
print(f" - Composants UI: {len([c for c in server.components.values() if c.category == 'ui'])}")
|
|
69
|
+
print(f" - Composants fonctionnels: {len([c for c in server.components.values() if c.category == 'functional'])}")
|
|
70
|
+
print(f" - Documentation chargée: {len(server.documentation)} sections")
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
asyncio.run(test_server())
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supersoniks/concorde",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "",
|
|
@@ -321,6 +321,7 @@
|
|
|
321
321
|
"@vitejs/plugin-basic-ssl": "^2.1.0",
|
|
322
322
|
"altcha": "^1.0.7",
|
|
323
323
|
"autoprefixer": "^10.4.19",
|
|
324
|
+
"baseline-browser-mapping": "^2.8.31",
|
|
324
325
|
"jsdom": "^26.0.0",
|
|
325
326
|
"lit": "^3.1.3",
|
|
326
327
|
"marked": "^12.0.1",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/* *
|
|
3
|
+
* Call get-challenge on auto-hosted latcha service at https://altcha.supersoniks.org
|
|
4
|
+
* */
|
|
5
|
+
|
|
6
|
+
// Autoriser toutes les origines
|
|
7
|
+
header("Access-Control-Allow-Origin: *");
|
|
8
|
+
|
|
9
|
+
// Autoriser les méthodes HTTP spécifiques
|
|
10
|
+
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
|
|
11
|
+
|
|
12
|
+
// Autoriser certains en-têtes spécifiques
|
|
13
|
+
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
|
14
|
+
|
|
15
|
+
// Si la méthode est OPTIONS, terminer la requête ici
|
|
16
|
+
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
17
|
+
http_response_code(200);
|
|
18
|
+
exit();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getChallenge($key){
|
|
22
|
+
$maxNumber=20000;
|
|
23
|
+
$queryString = $params = [
|
|
24
|
+
'key' => $key,
|
|
25
|
+
'maxNumber' => $maxNumber
|
|
26
|
+
];
|
|
27
|
+
// Générer la chaîne de requête
|
|
28
|
+
$queryString = http_build_query($params);
|
|
29
|
+
$url = "https://altcha.supersoniks.org/get-challenge?key=".$queryString;
|
|
30
|
+
$response = file_get_contents($url);
|
|
31
|
+
return $response;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
echo getChallenge($_GET['key']);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/* *
|
|
3
|
+
* Call verify-solution on auto-hosted latcha service at https://altcha.supersoniks.org
|
|
4
|
+
* */
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// Autoriser toutes les origines
|
|
8
|
+
header("Access-Control-Allow-Origin: *");
|
|
9
|
+
|
|
10
|
+
// Autoriser les méthodes HTTP spécifiques
|
|
11
|
+
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
|
|
12
|
+
|
|
13
|
+
// Autoriser certains en-têtes spécifiques
|
|
14
|
+
header("Access-Control-Allow-Headers: Content-Type, Authorization, x-altcha-spam-filter");
|
|
15
|
+
|
|
16
|
+
// Si la méthode est OPTIONS, terminer la requête ici
|
|
17
|
+
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
18
|
+
http_response_code(200);
|
|
19
|
+
exit();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function verifySolution($key, $solution){
|
|
23
|
+
$queryString = $params = [
|
|
24
|
+
'key' => $key,
|
|
25
|
+
'altcha' => $solution
|
|
26
|
+
];
|
|
27
|
+
// Générer la chaîne de requête
|
|
28
|
+
$queryString = http_build_query($params);
|
|
29
|
+
$url = "https://altcha.supersoniks.org/verify-solution?".$queryString;
|
|
30
|
+
$response = file_get_contents($url);
|
|
31
|
+
return $response;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get json posted data
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
// Get the posted data
|
|
39
|
+
|
|
40
|
+
$data = json_decode(file_get_contents("php://input"));
|
|
41
|
+
|
|
42
|
+
echo verifySolution($data->captchakey, $data->captchatoken);
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
The **sonic-fetch** component is used to request and store data from an API.
|
|
3
3
|
Fetch extends the mixins Fetcher and [Subscriber](#docs/_core-concept/subscriber.md/subscriber)
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
## Basic usage
|
|
6
10
|
In order to work properly the <b>sonic-fetch</b> component needs at least the following attributes.
|
|
7
11
|
- **serviceURL** : A base service url. This attribute can be inherited from an ancestor.
|
|
@@ -11,6 +15,8 @@ In order to work properly the <b>sonic-fetch</b> component needs at least the fo
|
|
|
11
15
|
- **dataProvider *(Required)*** : An ID that is used as a reference to the object storing the data returned by the API.
|
|
12
16
|
This attribute can be inherited from an ancestor.
|
|
13
17
|
|
|
18
|
+
|
|
19
|
+
|
|
14
20
|
<sonic-code>
|
|
15
21
|
<template>
|
|
16
22
|
<sonic-fetch serviceURL="https://reqres.in" endPoint="api/users?page=2" dataProvider="myDataObj"></sonic-fetch>
|
|
File without changes
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
SDUINode,
|
|
6
6
|
SDUITransformDescription,
|
|
7
7
|
} from "@supersoniks/concorde/core/components/functional/sdui/types";
|
|
8
|
-
import {Fetcher, Subscriber} from "@supersoniks/concorde/mixins";
|
|
8
|
+
import { Fetcher, Subscriber } from "@supersoniks/concorde/mixins";
|
|
9
9
|
|
|
10
|
-
import {HTML, Objects} from "@supersoniks/concorde/utils";
|
|
11
|
-
import {LitElement, PropertyValues} from "lit";
|
|
12
|
-
import {customElement, property} from "lit/decorators.js";
|
|
10
|
+
import { HTML, Objects } from "@supersoniks/concorde/utils";
|
|
11
|
+
import { LitElement, PropertyValues } from "lit";
|
|
12
|
+
import { customElement, property } from "lit/decorators.js";
|
|
13
13
|
const tagName = "sonic-sdui"; // For Astro.build
|
|
14
14
|
/**
|
|
15
15
|
* ### sonic-sdui (Server Driven User Interface) est un fetcher chargant un JSON décrivant une interface utilisateur
|
|
@@ -75,7 +75,9 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
75
75
|
* Suppressiond du contenu du composant avant le génération de la nouvelle ui
|
|
76
76
|
*/
|
|
77
77
|
private removeChildren() {
|
|
78
|
-
while (
|
|
78
|
+
while (
|
|
79
|
+
[...this.children].filter((elt) => elt.nodeName != "SLOT").length > 0
|
|
80
|
+
) {
|
|
79
81
|
this.removeChild(this.children[0]);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -118,9 +120,12 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
118
120
|
if (!this.sduiDescriptor) return;
|
|
119
121
|
let nodes = this.sduiDescriptor.nodes;
|
|
120
122
|
if (!nodes) nodes = [];
|
|
121
|
-
const messageProvider = {
|
|
123
|
+
const messageProvider = {
|
|
124
|
+
tagName: "sonic-toast-message-subscriber",
|
|
125
|
+
attributes: {},
|
|
126
|
+
};
|
|
122
127
|
if (this.messagesKey) {
|
|
123
|
-
messageProvider.attributes = {subDataProvider: this.messagesKey};
|
|
128
|
+
messageProvider.attributes = { subDataProvider: this.messagesKey };
|
|
124
129
|
}
|
|
125
130
|
nodes.push(messageProvider);
|
|
126
131
|
nodes.forEach((node) => this.appendChild(this.parseChild(node)));
|
|
@@ -130,7 +135,7 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
130
135
|
*/
|
|
131
136
|
private parseChild(node: SDUINode) {
|
|
132
137
|
const tagName = node.tagName || "div";
|
|
133
|
-
let {element, contentElement} = this.handleLibrary(node, tagName);
|
|
138
|
+
let { element, contentElement } = this.handleLibrary(node, tagName);
|
|
134
139
|
this.handleAttributes(node, element);
|
|
135
140
|
element = this.handleMarkup(node, element);
|
|
136
141
|
if (!contentElement) contentElement = element;
|
|
@@ -148,7 +153,8 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
148
153
|
*/
|
|
149
154
|
private handlePrefixSuffix(node: SDUINode, element: HTMLElement) {
|
|
150
155
|
const container = document.createElement("div");
|
|
151
|
-
container.innerHTML =
|
|
156
|
+
container.innerHTML =
|
|
157
|
+
(node.prefix || "") + element.outerHTML + (node.suffix || "");
|
|
152
158
|
container.style.display = "contents";
|
|
153
159
|
return container;
|
|
154
160
|
}
|
|
@@ -156,18 +162,26 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
156
162
|
* Création des enfants du noeud courant
|
|
157
163
|
* Si l'enfant à un attribut parentElementSelector, il est ajouté dans le noeud correspondant au sélecteur css associé et non pas dans l'élément directement.
|
|
158
164
|
*/
|
|
159
|
-
private handleChildNodes(
|
|
165
|
+
private handleChildNodes(
|
|
166
|
+
node: SDUINode,
|
|
167
|
+
contentElement: HTMLElement,
|
|
168
|
+
element: HTMLElement
|
|
169
|
+
) {
|
|
160
170
|
if (node.nodes) {
|
|
161
171
|
const children: Array<SDUINode> = node.nodes;
|
|
162
172
|
for (const child of children) {
|
|
163
173
|
const childElement = this.parseChild(child);
|
|
164
174
|
let nodeToAppendOn = contentElement;
|
|
165
175
|
if (child.parentElementSelector) {
|
|
166
|
-
nodeToAppendOn =
|
|
176
|
+
nodeToAppendOn =
|
|
177
|
+
element.querySelector(child.parentElementSelector) ||
|
|
178
|
+
contentElement;
|
|
167
179
|
}
|
|
168
|
-
if (nodeToAppendOn.shadowRoot)
|
|
180
|
+
if (nodeToAppendOn.shadowRoot)
|
|
181
|
+
nodeToAppendOn.shadowRoot.appendChild(childElement);
|
|
169
182
|
else if (nodeToAppendOn.tagName.toLocaleLowerCase() == "template") {
|
|
170
|
-
const template: HTMLTemplateElement =
|
|
183
|
+
const template: HTMLTemplateElement =
|
|
184
|
+
nodeToAppendOn as HTMLTemplateElement;
|
|
171
185
|
template.content.appendChild(childElement);
|
|
172
186
|
} else nodeToAppendOn.appendChild(childElement);
|
|
173
187
|
}
|
|
@@ -184,11 +198,15 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
184
198
|
let element: HTMLElement;
|
|
185
199
|
let contentElement: HTMLElement | undefined;
|
|
186
200
|
if (node.libraryKey && this.sduiDescriptor.library) {
|
|
187
|
-
element = this.parseChild(
|
|
188
|
-
|
|
189
|
-
|
|
201
|
+
element = this.parseChild(
|
|
202
|
+
this.sduiDescriptor.library[node.libraryKey] || { tagName: "div" }
|
|
203
|
+
);
|
|
204
|
+
const selector = (this.sduiDescriptor.library[node.libraryKey] || {})
|
|
205
|
+
.contentElementSelector;
|
|
206
|
+
if (selector)
|
|
207
|
+
contentElement = element.querySelector(selector) as HTMLElement;
|
|
190
208
|
} else element = document.createElement(tagName) as HTMLElement;
|
|
191
|
-
return {element, contentElement};
|
|
209
|
+
return { element, contentElement };
|
|
192
210
|
}
|
|
193
211
|
/**
|
|
194
212
|
* Remplissage des attributs html avec les attributs fournis dans le noeud
|
|
@@ -197,7 +215,9 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
197
215
|
const attributes = node.attributes;
|
|
198
216
|
for (const k in attributes) {
|
|
199
217
|
const attrData: object | string = attributes[k];
|
|
200
|
-
const attr: string = Objects.isObject(attrData)
|
|
218
|
+
const attr: string = Objects.isObject(attrData)
|
|
219
|
+
? JSON.stringify(attrData)
|
|
220
|
+
: attrData;
|
|
201
221
|
element.setAttribute(k, attr);
|
|
202
222
|
}
|
|
203
223
|
}
|
|
@@ -216,13 +236,18 @@ export class SonicSDUI extends Fetcher(Subscriber(LitElement)) {
|
|
|
216
236
|
/**
|
|
217
237
|
* si le noeud à une propriété innerHTML, on l'ajout ay innerHTML de l'élément html en cours de création
|
|
218
238
|
*/
|
|
219
|
-
private handleInnerHTML(
|
|
239
|
+
private handleInnerHTML(
|
|
240
|
+
node: SDUINode,
|
|
241
|
+
contentElement: HTMLElement | undefined
|
|
242
|
+
) {
|
|
220
243
|
if (!node.innerHTML) return;
|
|
221
244
|
if (node.innerHTML.indexOf("wording_") != -1) {
|
|
222
245
|
const wordingProvider = this.getAncestorAttributeValue("wordingProvider");
|
|
223
|
-
this.api
|
|
224
|
-
|
|
225
|
-
|
|
246
|
+
this.api
|
|
247
|
+
?.post(wordingProvider, { labels: [node.innerHTML.substring(8)] })
|
|
248
|
+
.then((value) => {
|
|
249
|
+
if (contentElement) contentElement.innerHTML += value;
|
|
250
|
+
});
|
|
226
251
|
} else if (contentElement) {
|
|
227
252
|
contentElement.innerHTML += node.innerHTML;
|
|
228
253
|
}
|
|
@@ -184,6 +184,12 @@ export class Checkbox extends FormCheckable(
|
|
|
184
184
|
willUpdate(changedProperties: PropertyValues) {
|
|
185
185
|
this.hasSlotOrProps();
|
|
186
186
|
super.willUpdate(changedProperties);
|
|
187
|
+
/**
|
|
188
|
+
* On force le type à checkbox pour les checkbox
|
|
189
|
+
*/
|
|
190
|
+
if (changedProperties.has("type")) {
|
|
191
|
+
this.type = "checkbox";
|
|
192
|
+
}
|
|
187
193
|
}
|
|
188
194
|
|
|
189
195
|
hasSlotOrProps() {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
property,
|
|
5
5
|
queryAssignedNodes,
|
|
6
6
|
state,
|
|
7
|
+
query,
|
|
7
8
|
} from "lit/decorators.js";
|
|
8
9
|
import {
|
|
9
10
|
FormInput,
|
|
@@ -23,6 +24,7 @@ import { Input } from "@supersoniks/concorde/core/components/ui/form/input/input
|
|
|
23
24
|
import { customScroll } from "@supersoniks/concorde/core/components/ui/_css/scroll";
|
|
24
25
|
import { ResizeController } from "@lit-labs/observers/resize-controller.js";
|
|
25
26
|
import { traverseDotNotation } from "@supersoniks/concorde/core/utils/Objects";
|
|
27
|
+
import { Pop } from "../../pop/pop";
|
|
26
28
|
|
|
27
29
|
type ListItem = Record<string, string>;
|
|
28
30
|
|
|
@@ -82,6 +84,7 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
82
84
|
slotInputPrefixNodes!: Array<Node>;
|
|
83
85
|
|
|
84
86
|
@state() hasInputPrefix = false;
|
|
87
|
+
@query("sonic-pop") popElement!: Pop;
|
|
85
88
|
_resizeController = new ResizeController(this, {});
|
|
86
89
|
|
|
87
90
|
@state() isPopVisible = false;
|
|
@@ -324,9 +327,13 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
324
327
|
return this.searchPublisher?.get();
|
|
325
328
|
}
|
|
326
329
|
|
|
330
|
+
handleFocus(): void {
|
|
331
|
+
this.popElement.show();
|
|
332
|
+
}
|
|
333
|
+
|
|
327
334
|
render() {
|
|
328
335
|
return html`
|
|
329
|
-
<sonic-pop
|
|
336
|
+
<sonic-pop manual style="display:block;" @hide=${this.handleHide}>
|
|
330
337
|
<sonic-input
|
|
331
338
|
class="form-element"
|
|
332
339
|
dataProvider="${this.initSearchDataProvider + Math.random()}"
|
|
@@ -344,6 +351,7 @@ export class InputAutocomplete extends TemplatesContainer(
|
|
|
344
351
|
clearable
|
|
345
352
|
inlineContent
|
|
346
353
|
size=${this.size}
|
|
354
|
+
@focus=${this.handleFocus}
|
|
347
355
|
value=${ifDefined(this.getInputValue())}
|
|
348
356
|
>
|
|
349
357
|
<slot
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { css } from "lit";
|
|
1
|
+
import { css, PropertyValues } from "lit";
|
|
2
2
|
import { customElement } from "lit/decorators.js";
|
|
3
3
|
import { Checkbox } from "@supersoniks/concorde/core/components/ui/form/checkbox/checkbox";
|
|
4
4
|
|
|
@@ -37,6 +37,16 @@ export class Radio extends Checkbox {
|
|
|
37
37
|
super();
|
|
38
38
|
this.radio = true;
|
|
39
39
|
}
|
|
40
|
+
willUpdate(changedProperties: PropertyValues) {
|
|
41
|
+
const typeChanged = changedProperties.has("type");
|
|
42
|
+
super.willUpdate(changedProperties);
|
|
43
|
+
/**
|
|
44
|
+
* On force le type a radio pour tous les boutons radio
|
|
45
|
+
*/
|
|
46
|
+
if (typeChanged) {
|
|
47
|
+
this.type = "radio";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
40
50
|
connectedCallback() {
|
|
41
51
|
// this.iconName = "circle-small";
|
|
42
52
|
// this.iconPrefix = "solid";
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -210,10 +210,58 @@ export class SonicToastItem extends LitElement {
|
|
|
210
210
|
@property({ type: Boolean }) dismissForever = false;
|
|
211
211
|
@property({ type: String }) maxHeight = "10rem";
|
|
212
212
|
@state() visible = true;
|
|
213
|
+
@state() private _titleId: string = "";
|
|
213
214
|
|
|
214
215
|
// @queryAssignedElements({flatten: true, slot: main"})
|
|
215
216
|
// textSlot!: HTMLElement[];
|
|
216
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Retourne le rôle ARIA approprié selon le statut du toast
|
|
220
|
+
* - "alert" pour les erreurs (messages critiques) - implique déjà aria-live="assertive"
|
|
221
|
+
* - "status" pour les autres (messages informatifs)
|
|
222
|
+
*/
|
|
223
|
+
getAriaRole(): "alert" | "status" {
|
|
224
|
+
return this.status === "error" ? "alert" : "status";
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Retourne la valeur aria-live appropriée selon le statut
|
|
229
|
+
* - null pour les erreurs car role="alert" implique déjà aria-live="assertive"
|
|
230
|
+
* - "polite" pour les autres (peut attendre)
|
|
231
|
+
*/
|
|
232
|
+
getAriaLive(): "polite" | null {
|
|
233
|
+
return this.status === "error" ? null : "polite";
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Génère et mémorise un ID unique pour le titre du toast
|
|
238
|
+
*/
|
|
239
|
+
getTitleId(): string {
|
|
240
|
+
if (this._titleId) {
|
|
241
|
+
return this._titleId;
|
|
242
|
+
}
|
|
243
|
+
this._titleId = this.id
|
|
244
|
+
? `toast-title-${this.id}`
|
|
245
|
+
: `toast-title-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
246
|
+
return this._titleId;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Génère un label ARIA descriptif pour le bouton de fermeture
|
|
251
|
+
*/
|
|
252
|
+
getCloseButtonLabel(): string {
|
|
253
|
+
const statusLabels: Record<string, string> = {
|
|
254
|
+
error: "Fermer le message d'erreur",
|
|
255
|
+
warning: "Fermer l'avertissement",
|
|
256
|
+
success: "Fermer le message de succès",
|
|
257
|
+
info: "Fermer l'information",
|
|
258
|
+
};
|
|
259
|
+
const statusLabel = this.status
|
|
260
|
+
? statusLabels[this.status] || "Fermer la notification"
|
|
261
|
+
: "Fermer la notification";
|
|
262
|
+
return statusLabel;
|
|
263
|
+
}
|
|
264
|
+
|
|
217
265
|
render() {
|
|
218
266
|
// check if the toast is dismissed
|
|
219
267
|
if (this.dismissForever) {
|
|
@@ -228,11 +276,26 @@ export class SonicToastItem extends LitElement {
|
|
|
228
276
|
return nothing;
|
|
229
277
|
}
|
|
230
278
|
|
|
279
|
+
const titleId = this.title ? this.getTitleId() : undefined;
|
|
280
|
+
// Extrait un label pour aria-label si pas de titre, en essayant de couper proprement
|
|
281
|
+
const ariaLabel =
|
|
282
|
+
!this.title && this.text
|
|
283
|
+
? this.text.length > 100
|
|
284
|
+
? this.text.substring(0, 100).replace(/\s+\S*$/, "") + "..."
|
|
285
|
+
: this.text
|
|
286
|
+
: undefined;
|
|
287
|
+
|
|
288
|
+
const ariaLive = this.getAriaLive();
|
|
289
|
+
|
|
231
290
|
return html`<div
|
|
232
291
|
class="sonic-toast ${this.status} ${this.ghost ? "ghost" : ""}"
|
|
292
|
+
role=${this.getAriaRole()}
|
|
293
|
+
aria-live=${ariaLive || nothing}
|
|
294
|
+
aria-atomic="true"
|
|
295
|
+
aria-label=${ariaLabel || nothing}
|
|
233
296
|
>
|
|
234
297
|
<button
|
|
235
|
-
aria-label
|
|
298
|
+
aria-label=${this.getCloseButtonLabel()}
|
|
236
299
|
class="sonic-toast-close"
|
|
237
300
|
@click=${() => this.hide()}
|
|
238
301
|
>
|
|
@@ -247,11 +310,14 @@ export class SonicToastItem extends LitElement {
|
|
|
247
310
|
name=${icon[this.status]}
|
|
248
311
|
class="sonic-toast-icon"
|
|
249
312
|
size="2xl"
|
|
313
|
+
aria-hidden="true"
|
|
250
314
|
></sonic-icon>`}
|
|
251
315
|
|
|
252
316
|
<div class="sonic-toast-text">
|
|
253
317
|
${this.title
|
|
254
|
-
? html`<div class="sonic-toast-title"
|
|
318
|
+
? html`<div class="sonic-toast-title" id=${titleId}>
|
|
319
|
+
${this.title}
|
|
320
|
+
</div>`
|
|
255
321
|
: ""}
|
|
256
322
|
${this.text ? unsafeHTML(this.text) : ""}
|
|
257
323
|
<slot></slot>
|