@blackcube/aurelia2-bleet 1.0.0
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/blackcube-aurelia2-bleet-1.0.0.tgz +0 -0
- package/dist/index.es.js +4514 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.js +4549 -0
- package/dist/index.js.map +1 -0
- package/dist/types/attributes/ajaxify-trigger.d.ts +36 -0
- package/dist/types/attributes/ajaxify-trigger.d.ts.map +1 -0
- package/dist/types/attributes/alert.d.ts +15 -0
- package/dist/types/attributes/alert.d.ts.map +1 -0
- package/dist/types/attributes/badge.d.ts +13 -0
- package/dist/types/attributes/badge.d.ts.map +1 -0
- package/dist/types/attributes/burger.d.ts +11 -0
- package/dist/types/attributes/burger.d.ts.map +1 -0
- package/dist/types/attributes/drawer-trigger.d.ts +16 -0
- package/dist/types/attributes/drawer-trigger.d.ts.map +1 -0
- package/dist/types/attributes/dropdown.d.ts +38 -0
- package/dist/types/attributes/dropdown.d.ts.map +1 -0
- package/dist/types/attributes/index.d.ts +16 -0
- package/dist/types/attributes/index.d.ts.map +1 -0
- package/dist/types/attributes/menu.d.ts +32 -0
- package/dist/types/attributes/menu.d.ts.map +1 -0
- package/dist/types/attributes/modal-trigger.d.ts +16 -0
- package/dist/types/attributes/modal-trigger.d.ts.map +1 -0
- package/dist/types/attributes/pager.d.ts +13 -0
- package/dist/types/attributes/pager.d.ts.map +1 -0
- package/dist/types/attributes/password.d.ts +15 -0
- package/dist/types/attributes/password.d.ts.map +1 -0
- package/dist/types/attributes/profile.d.ts +24 -0
- package/dist/types/attributes/profile.d.ts.map +1 -0
- package/dist/types/attributes/select.d.ts +24 -0
- package/dist/types/attributes/select.d.ts.map +1 -0
- package/dist/types/attributes/tabs.d.ts +16 -0
- package/dist/types/attributes/tabs.d.ts.map +1 -0
- package/dist/types/attributes/toaster-trigger.d.ts +19 -0
- package/dist/types/attributes/toaster-trigger.d.ts.map +1 -0
- package/dist/types/attributes/upload.d.ts +57 -0
- package/dist/types/attributes/upload.d.ts.map +1 -0
- package/dist/types/codecs/ajaxify-codec.d.ts +5 -0
- package/dist/types/codecs/ajaxify-codec.d.ts.map +1 -0
- package/dist/types/codecs/csrf-codec.d.ts +7 -0
- package/dist/types/codecs/csrf-codec.d.ts.map +1 -0
- package/dist/types/codecs/request-codec.d.ts +5 -0
- package/dist/types/codecs/request-codec.d.ts.map +1 -0
- package/dist/types/components/bleet-ajaxify.d.ts +17 -0
- package/dist/types/components/bleet-ajaxify.d.ts.map +1 -0
- package/dist/types/components/bleet-ajaxify.html.d.ts +3 -0
- package/dist/types/components/bleet-ajaxify.html.d.ts.map +1 -0
- package/dist/types/components/bleet-drawer.d.ts +40 -0
- package/dist/types/components/bleet-drawer.d.ts.map +1 -0
- package/dist/types/components/bleet-drawer.html.d.ts +3 -0
- package/dist/types/components/bleet-drawer.html.d.ts.map +1 -0
- package/dist/types/components/bleet-modal.d.ts +46 -0
- package/dist/types/components/bleet-modal.d.ts.map +1 -0
- package/dist/types/components/bleet-modal.html.d.ts +3 -0
- package/dist/types/components/bleet-modal.html.d.ts.map +1 -0
- package/dist/types/components/bleet-overlay.d.ts +21 -0
- package/dist/types/components/bleet-overlay.d.ts.map +1 -0
- package/dist/types/components/bleet-quilljs.d.ts +19 -0
- package/dist/types/components/bleet-quilljs.d.ts.map +1 -0
- package/dist/types/components/bleet-quilljs.html.d.ts +3 -0
- package/dist/types/components/bleet-quilljs.html.d.ts.map +1 -0
- package/dist/types/components/bleet-toast.d.ts +26 -0
- package/dist/types/components/bleet-toast.d.ts.map +1 -0
- package/dist/types/components/bleet-toast.html.d.ts +3 -0
- package/dist/types/components/bleet-toast.html.d.ts.map +1 -0
- package/dist/types/components/bleet-toaster-trigger.d.ts +20 -0
- package/dist/types/components/bleet-toaster-trigger.d.ts.map +1 -0
- package/dist/types/components/bleet-toaster.d.ts +15 -0
- package/dist/types/components/bleet-toaster.d.ts.map +1 -0
- package/dist/types/components/bleet-toaster.html.d.ts +3 -0
- package/dist/types/components/bleet-toaster.html.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +9 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/types/configure.d.ts +35 -0
- package/dist/types/configure.d.ts.map +1 -0
- package/dist/types/enums/api.d.ts +11 -0
- package/dist/types/enums/api.d.ts.map +1 -0
- package/dist/types/enums/event-aggregator.d.ts +123 -0
- package/dist/types/enums/event-aggregator.d.ts.map +1 -0
- package/dist/types/index.d.ts +26 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/interfaces/api.d.ts +56 -0
- package/dist/types/interfaces/api.d.ts.map +1 -0
- package/dist/types/interfaces/dialog.d.ts +18 -0
- package/dist/types/interfaces/dialog.d.ts.map +1 -0
- package/dist/types/interfaces/event-aggregator.d.ts +75 -0
- package/dist/types/interfaces/event-aggregator.d.ts.map +1 -0
- package/dist/types/services/api-service.d.ts +64 -0
- package/dist/types/services/api-service.d.ts.map +1 -0
- package/dist/types/services/http-service.d.ts +22 -0
- package/dist/types/services/http-service.d.ts.map +1 -0
- package/dist/types/services/socketio-service.d.ts +23 -0
- package/dist/types/services/socketio-service.d.ts.map +1 -0
- package/dist/types/services/storage-service.d.ts +13 -0
- package/dist/types/services/storage-service.d.ts.map +1 -0
- package/dist/types/services/svg-service.d.ts +17 -0
- package/dist/types/services/svg-service.d.ts.map +1 -0
- package/dist/types/services/transition-service.d.ts +13 -0
- package/dist/types/services/transition-service.d.ts.map +1 -0
- package/dist/types/services/trap-focus-service.d.ts +28 -0
- package/dist/types/services/trap-focus-service.d.ts.map +1 -0
- package/doc/bleet-api-reference.md +1333 -0
- package/doc/bleet-model-api-reference.md +379 -0
- package/doc/bleet-typescript-api-reference.md +1037 -0
- package/package.json +43 -0
- package/resource.d.ts +22 -0
- package/src/attributes/ajaxify-trigger.ts +218 -0
- package/src/attributes/alert.ts +55 -0
- package/src/attributes/badge.ts +39 -0
- package/src/attributes/burger.ts +36 -0
- package/src/attributes/drawer-trigger.ts +53 -0
- package/src/attributes/dropdown.ts +377 -0
- package/src/attributes/index.ts +15 -0
- package/src/attributes/menu.ts +179 -0
- package/src/attributes/modal-trigger.ts +53 -0
- package/src/attributes/pager.ts +43 -0
- package/src/attributes/password.ts +47 -0
- package/src/attributes/profile.ts +112 -0
- package/src/attributes/select.ts +214 -0
- package/src/attributes/tabs.ts +99 -0
- package/src/attributes/toaster-trigger.ts +54 -0
- package/src/attributes/upload.ts +380 -0
- package/src/codecs/ajaxify-codec.ts +16 -0
- package/src/codecs/csrf-codec.ts +41 -0
- package/src/codecs/request-codec.ts +16 -0
- package/src/components/bleet-ajaxify.html.ts +4 -0
- package/src/components/bleet-ajaxify.ts +62 -0
- package/src/components/bleet-drawer.html.ts +36 -0
- package/src/components/bleet-drawer.ts +236 -0
- package/src/components/bleet-modal.html.ts +30 -0
- package/src/components/bleet-modal.ts +274 -0
- package/src/components/bleet-overlay.ts +111 -0
- package/src/components/bleet-quilljs.html.ts +4 -0
- package/src/components/bleet-quilljs.ts +73 -0
- package/src/components/bleet-toast.html.ts +44 -0
- package/src/components/bleet-toast.ts +133 -0
- package/src/components/bleet-toaster-trigger.ts +66 -0
- package/src/components/bleet-toaster.html.ts +11 -0
- package/src/components/bleet-toaster.ts +72 -0
- package/src/components/index.ts +8 -0
- package/src/configure.ts +121 -0
- package/src/enums/api.ts +12 -0
- package/src/enums/event-aggregator.ts +131 -0
- package/src/index.ts +220 -0
- package/src/interfaces/api.ts +64 -0
- package/src/interfaces/dialog.ts +25 -0
- package/src/interfaces/event-aggregator.ts +88 -0
- package/src/services/api-service.ts +387 -0
- package/src/services/http-service.ts +166 -0
- package/src/services/socketio-service.ts +138 -0
- package/src/services/storage-service.ts +36 -0
- package/src/services/svg-service.ts +35 -0
- package/src/services/transition-service.ts +39 -0
- package/src/services/trap-focus-service.ts +213 -0
- package/src/types/css.d.ts +4 -0
- package/src/types/html.d.ts +12 -0
- package/src/types/svg.d.ts +4 -0
package/dist/index.es.js
ADDED
|
@@ -0,0 +1,4514 @@
|
|
|
1
|
+
import { DI, resolve, ILogger, IPlatform, customAttribute, IEventAggregator, INode, bindable, customElement, queueTask } from 'aurelia';
|
|
2
|
+
import { IHttpClient } from '@aurelia/fetch-client';
|
|
3
|
+
import Resumable from 'resumablejs';
|
|
4
|
+
import Quill from 'quill';
|
|
5
|
+
|
|
6
|
+
var Transport;
|
|
7
|
+
(function (Transport) {
|
|
8
|
+
Transport["Socketio"] = "socketio";
|
|
9
|
+
Transport["Http"] = "http";
|
|
10
|
+
})(Transport || (Transport = {}));
|
|
11
|
+
|
|
12
|
+
const IBleetConfiguration = DI.createInterface('IBleetConfiguration', x => x.singleton(Configure));
|
|
13
|
+
class Configure {
|
|
14
|
+
_config = {
|
|
15
|
+
transports: Transport.Http,
|
|
16
|
+
csrf: {
|
|
17
|
+
enabled: true,
|
|
18
|
+
metaName: 'csrf',
|
|
19
|
+
headerName: 'X-CSRF-Token',
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
_container = null;
|
|
23
|
+
_transportInterfaces = new Map();
|
|
24
|
+
setContainer(container) {
|
|
25
|
+
this._container = container;
|
|
26
|
+
}
|
|
27
|
+
getContainer() {
|
|
28
|
+
return this._container;
|
|
29
|
+
}
|
|
30
|
+
registerTransportInterface(type, iface) {
|
|
31
|
+
this._transportInterfaces.set(type, iface);
|
|
32
|
+
}
|
|
33
|
+
getCsrfConfig() {
|
|
34
|
+
return this._config.csrf ?? { enabled: true, metaName: 'csrf', headerName: 'X-CSRF-Token' };
|
|
35
|
+
}
|
|
36
|
+
getConfig() {
|
|
37
|
+
return this._config;
|
|
38
|
+
}
|
|
39
|
+
get(key) {
|
|
40
|
+
return this._config[key];
|
|
41
|
+
}
|
|
42
|
+
set(key, val) {
|
|
43
|
+
this._config[key] = val;
|
|
44
|
+
return val;
|
|
45
|
+
}
|
|
46
|
+
getTransports() {
|
|
47
|
+
const cfg = this._config.transports ?? Transport.Http;
|
|
48
|
+
const entries = Array.isArray(cfg) ? cfg : [cfg];
|
|
49
|
+
return entries.map(entry => this.isTransportWithConfig(entry) ? entry.type : entry);
|
|
50
|
+
}
|
|
51
|
+
getBaseUrl(transport) {
|
|
52
|
+
const cfg = this._config.transports ?? Transport.Http;
|
|
53
|
+
const entries = Array.isArray(cfg) ? cfg : [cfg];
|
|
54
|
+
const entry = entries.find(e => this.isTransportWithConfig(e) ? e.type === transport : e === transport);
|
|
55
|
+
if (entry && this.isTransportWithConfig(entry) && entry.baseUrl !== undefined) {
|
|
56
|
+
return entry.baseUrl;
|
|
57
|
+
}
|
|
58
|
+
return this._config.baseUrl ?? '';
|
|
59
|
+
}
|
|
60
|
+
isTransportWithConfig(entry) {
|
|
61
|
+
return typeof entry === 'object' && 'type' in entry;
|
|
62
|
+
}
|
|
63
|
+
getTransport(type) {
|
|
64
|
+
if (!this._container) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
// HTTP : déjà enregistré
|
|
68
|
+
const iface = this._transportInterfaces.get(type);
|
|
69
|
+
if (iface) {
|
|
70
|
+
return this._container.get(iface);
|
|
71
|
+
}
|
|
72
|
+
// Socketio : require() synchrone à la demande
|
|
73
|
+
if (type === Transport.Socketio) {
|
|
74
|
+
try {
|
|
75
|
+
const { ISocketioService } = require('./services/socketio-service');
|
|
76
|
+
this._transportInterfaces.set(type, ISocketioService);
|
|
77
|
+
return this._container.get(ISocketioService);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
throw new Error('Transport Socketio configuré mais socket.io-client non installé. ' +
|
|
81
|
+
'Installez-le avec : npm install socket.io-client');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
getAvailableTransports() {
|
|
87
|
+
return this.getTransports()
|
|
88
|
+
.map(t => this.getTransport(t))
|
|
89
|
+
.filter((t) => t !== null);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const IHttpService = DI.createInterface('IHttpService', (x) => x.singleton(HttpService));
|
|
94
|
+
class HttpService {
|
|
95
|
+
logger;
|
|
96
|
+
httpClient;
|
|
97
|
+
config;
|
|
98
|
+
type = Transport.Http;
|
|
99
|
+
constructor(logger = resolve(ILogger).scopeTo('HttpService'), httpClient = resolve(IHttpClient), config = resolve(IBleetConfiguration)) {
|
|
100
|
+
this.logger = logger;
|
|
101
|
+
this.httpClient = httpClient;
|
|
102
|
+
this.config = config;
|
|
103
|
+
this.logger.trace('constructor');
|
|
104
|
+
this.httpClient.configure((config) => {
|
|
105
|
+
config.withDefaults({
|
|
106
|
+
headers: {
|
|
107
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
108
|
+
},
|
|
109
|
+
credentials: 'include'
|
|
110
|
+
});
|
|
111
|
+
return config;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
isAvailable() {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
prepareRequest(ctx) {
|
|
118
|
+
const baseUrl = this.config.getBaseUrl(Transport.Http);
|
|
119
|
+
let url = baseUrl + ctx.url;
|
|
120
|
+
const pathParams = ctx.pathParams ?? {};
|
|
121
|
+
// FormData: don't try to extract path params from it, keep as-is
|
|
122
|
+
if (ctx.data instanceof FormData) {
|
|
123
|
+
// Substitute :params in URL from pathParams only
|
|
124
|
+
const paramPattern = /:[a-zA-Z_][a-zA-Z0-9_-]*/g;
|
|
125
|
+
const matches = ctx.url.match(paramPattern) ?? [];
|
|
126
|
+
for (const match of matches) {
|
|
127
|
+
const paramName = match.slice(1);
|
|
128
|
+
if (paramName in pathParams) {
|
|
129
|
+
url = url.replace(match, encodeURIComponent(String(pathParams[paramName])));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
url,
|
|
134
|
+
method: ctx.method,
|
|
135
|
+
headers: ctx.headers,
|
|
136
|
+
data: ctx.data
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const remainingData = { ...ctx.data };
|
|
140
|
+
// Substitute :params in URL (explicit > implicit) and remove from payload
|
|
141
|
+
const paramPattern = /:[a-zA-Z_][a-zA-Z0-9_-]*/g;
|
|
142
|
+
const matches = ctx.url.match(paramPattern) ?? [];
|
|
143
|
+
for (const match of matches) {
|
|
144
|
+
const paramName = match.slice(1);
|
|
145
|
+
const value = paramName in pathParams ? pathParams[paramName] : remainingData[paramName];
|
|
146
|
+
url = url.replace(match, encodeURIComponent(String(value)));
|
|
147
|
+
delete remainingData[paramName];
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
url,
|
|
151
|
+
method: ctx.method,
|
|
152
|
+
headers: ctx.headers,
|
|
153
|
+
data: remainingData
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
execute(ctx, responseType = 'json') {
|
|
157
|
+
this.logger.trace('execute', ctx.method, ctx.url);
|
|
158
|
+
const hasBody = ['POST', 'PATCH', 'PUT', 'DELETE'].includes(ctx.method.toUpperCase());
|
|
159
|
+
const headers = { ...ctx.headers };
|
|
160
|
+
const init = {
|
|
161
|
+
method: ctx.method.toUpperCase(),
|
|
162
|
+
};
|
|
163
|
+
if (hasBody && ctx.data) {
|
|
164
|
+
if (ctx.data instanceof FormData) {
|
|
165
|
+
// FormData: don't set Content-Type, browser will set it with boundary
|
|
166
|
+
delete headers['Content-Type'];
|
|
167
|
+
init.body = ctx.data;
|
|
168
|
+
}
|
|
169
|
+
else if (Object.keys(ctx.data).length > 0) {
|
|
170
|
+
init.body = JSON.stringify(ctx.data);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
init.headers = headers;
|
|
174
|
+
return this.httpClient.fetch(ctx.url, init)
|
|
175
|
+
.then((response) => this.parseResponse(response, responseType));
|
|
176
|
+
}
|
|
177
|
+
parseResponse(response, responseType) {
|
|
178
|
+
const headers = {};
|
|
179
|
+
response.headers.forEach((value, key) => {
|
|
180
|
+
headers[key] = value;
|
|
181
|
+
});
|
|
182
|
+
const effectiveType = responseType === 'auto'
|
|
183
|
+
? this.detectResponseType(response.headers.get('Content-Type'))
|
|
184
|
+
: responseType;
|
|
185
|
+
return this.parseBody(response, effectiveType)
|
|
186
|
+
.then((body) => ({
|
|
187
|
+
statusCode: response.status,
|
|
188
|
+
headers,
|
|
189
|
+
body
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
detectResponseType(contentType) {
|
|
193
|
+
if (!contentType) {
|
|
194
|
+
return 'text';
|
|
195
|
+
}
|
|
196
|
+
const ct = contentType.toLowerCase();
|
|
197
|
+
if (ct.includes('application/json')) {
|
|
198
|
+
return 'json';
|
|
199
|
+
}
|
|
200
|
+
if (ct.startsWith('text/')) {
|
|
201
|
+
return 'text';
|
|
202
|
+
}
|
|
203
|
+
if (ct.includes('application/')) {
|
|
204
|
+
return 'blob';
|
|
205
|
+
}
|
|
206
|
+
return 'text';
|
|
207
|
+
}
|
|
208
|
+
parseBody(response, responseType) {
|
|
209
|
+
switch (responseType) {
|
|
210
|
+
case 'json':
|
|
211
|
+
return response.json();
|
|
212
|
+
case 'text':
|
|
213
|
+
return response.text();
|
|
214
|
+
case 'blob':
|
|
215
|
+
return response.blob();
|
|
216
|
+
case 'arraybuffer':
|
|
217
|
+
return response.arrayBuffer();
|
|
218
|
+
default:
|
|
219
|
+
return response.json();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const ISvgService = /*@__PURE__*/ DI.createInterface('ISvgService', (x) => x.singleton(SvgService));
|
|
225
|
+
class SvgService {
|
|
226
|
+
logger;
|
|
227
|
+
static ICONS = {
|
|
228
|
+
'information-circle': `<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 0 1 .67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 1 1-.671-1.34l.041-.022ZM12 9a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd"/></svg>`,
|
|
229
|
+
'check-circle': `<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd"/></svg>`,
|
|
230
|
+
'exclamation-triangle': `<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd"/></svg>`,
|
|
231
|
+
'x-circle': `<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25Zm-1.72 6.97a.75.75 0 1 0-1.06 1.06L10.94 12l-1.72 1.72a.75.75 0 1 0 1.06 1.06L12 13.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L13.06 12l1.72-1.72a.75.75 0 1 0-1.06-1.06L12 10.94l-1.72-1.72Z" clip-rule="evenodd"/></svg>`,
|
|
232
|
+
'x-mark': `<svg class="size-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/></svg>`,
|
|
233
|
+
};
|
|
234
|
+
constructor(logger = resolve(ILogger).scopeTo('SvgService')) {
|
|
235
|
+
this.logger = logger;
|
|
236
|
+
this.logger.trace('constructor');
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Retourne le SVG pour une icône
|
|
240
|
+
* @param icon Clé heroicon (ex: 'check-circle') ou SVG inline custom
|
|
241
|
+
* @returns Le SVG du map si clé connue, sinon retourne icon tel quel (SVG custom)
|
|
242
|
+
*/
|
|
243
|
+
get(icon) {
|
|
244
|
+
this.logger.trace('get', icon);
|
|
245
|
+
if (!icon)
|
|
246
|
+
return null;
|
|
247
|
+
return SvgService.ICONS[icon] ?? icon;
|
|
248
|
+
}
|
|
249
|
+
has(key) {
|
|
250
|
+
return key in SvgService.ICONS;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
class CsrfCodec {
|
|
255
|
+
static codec = {
|
|
256
|
+
encode: (ctx) => {
|
|
257
|
+
const meta = document.querySelector('meta[name="csrf"]');
|
|
258
|
+
const token = meta?.getAttribute('content');
|
|
259
|
+
if (!token) {
|
|
260
|
+
return Promise.resolve(ctx);
|
|
261
|
+
}
|
|
262
|
+
return Promise.resolve({
|
|
263
|
+
...ctx,
|
|
264
|
+
headers: {
|
|
265
|
+
...ctx.headers,
|
|
266
|
+
'X-CSRF-Token': token,
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
static fromConfig(config) {
|
|
272
|
+
return {
|
|
273
|
+
encode: (ctx) => {
|
|
274
|
+
const meta = document.querySelector(`meta[name="${config.metaName}"]`);
|
|
275
|
+
const token = meta?.getAttribute('content');
|
|
276
|
+
if (!token) {
|
|
277
|
+
return Promise.resolve(ctx);
|
|
278
|
+
}
|
|
279
|
+
return Promise.resolve({
|
|
280
|
+
...ctx,
|
|
281
|
+
headers: {
|
|
282
|
+
...ctx.headers,
|
|
283
|
+
[config.headerName]: token,
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const IApiService = /*@__PURE__*/ DI.createInterface('IApiService', (x) => x.singleton(ApiService));
|
|
292
|
+
class ApiService {
|
|
293
|
+
logger;
|
|
294
|
+
config;
|
|
295
|
+
static PARAM_PATTERN = /:[a-zA-Z_][a-zA-Z0-9_-]*/g;
|
|
296
|
+
memoryCache = new Map();
|
|
297
|
+
constructor(logger = resolve(ILogger).scopeTo('ApiService'), config = resolve(IBleetConfiguration)) {
|
|
298
|
+
this.logger = logger;
|
|
299
|
+
this.config = config;
|
|
300
|
+
this.logger.trace('constructor');
|
|
301
|
+
}
|
|
302
|
+
url(path, params) {
|
|
303
|
+
return new ApiRequestBuilder(this, path, params);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Simple HTML fetch for AJAX dialogs (modal/drawer)
|
|
307
|
+
* Returns full response for status code checking
|
|
308
|
+
*/
|
|
309
|
+
async fetchHtml(url) {
|
|
310
|
+
this.logger.trace('fetchHtml', url);
|
|
311
|
+
return this.url(url).toText().get();
|
|
312
|
+
}
|
|
313
|
+
execute(request) {
|
|
314
|
+
this.logger.trace('execute', request.method, request.url);
|
|
315
|
+
// 1. Validate path params are present in pathParams or data
|
|
316
|
+
this.validateParams(request.url, request.pathParams, request.data);
|
|
317
|
+
// 2. Build request context
|
|
318
|
+
const initialCtx = {
|
|
319
|
+
url: request.url,
|
|
320
|
+
method: request.method,
|
|
321
|
+
headers: request.headers,
|
|
322
|
+
data: request.data,
|
|
323
|
+
pathParams: request.pathParams
|
|
324
|
+
};
|
|
325
|
+
// 3. Build codec chain : CSRF auto + user codecs
|
|
326
|
+
const csrfConfig = this.config.getCsrfConfig();
|
|
327
|
+
const allInputCodecs = [];
|
|
328
|
+
if (csrfConfig.enabled) {
|
|
329
|
+
allInputCodecs.push(CsrfCodec.fromConfig(csrfConfig));
|
|
330
|
+
}
|
|
331
|
+
allInputCodecs.push(...request.inputCodecs);
|
|
332
|
+
// 4. Apply input codecs (encode) — chaîne de promesses
|
|
333
|
+
const ctxPromise = allInputCodecs.reduce((promise, codec) => codec.encode ? promise.then((ctx) => codec.encode(ctx)) : promise, Promise.resolve(initialCtx));
|
|
334
|
+
return ctxPromise.then((ctx) => {
|
|
335
|
+
// 4. Check cache
|
|
336
|
+
if (request.cache) {
|
|
337
|
+
const cached = this.getFromCache(request, ctx);
|
|
338
|
+
if (cached) {
|
|
339
|
+
this.logger.trace('execute:cache-hit');
|
|
340
|
+
return Promise.resolve(cached);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// 5. Execute via transport avec fallback
|
|
344
|
+
return this.executeWithFallback(ctx, request.responseType)
|
|
345
|
+
.then((response) => {
|
|
346
|
+
// 6. Apply output codecs (decode)
|
|
347
|
+
return request.outputCodecs.reduce((promise, codec) => codec.decode ? promise.then((r) => codec.decode(r)) : promise, Promise.resolve(response));
|
|
348
|
+
})
|
|
349
|
+
.then((response) => {
|
|
350
|
+
// 7. Store in cache
|
|
351
|
+
if (request.cache) {
|
|
352
|
+
this.storeInCache(request, ctx, response);
|
|
353
|
+
}
|
|
354
|
+
return response;
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
executeWithFallback(ctx, responseType) {
|
|
359
|
+
const transports = this.config.getAvailableTransports();
|
|
360
|
+
if (transports.length === 0) {
|
|
361
|
+
return Promise.reject(new Error('No transport available'));
|
|
362
|
+
}
|
|
363
|
+
const tryTransport = (index, lastError) => {
|
|
364
|
+
if (index >= transports.length) {
|
|
365
|
+
return Promise.reject(lastError ?? new Error('All transports failed'));
|
|
366
|
+
}
|
|
367
|
+
const transport = transports[index];
|
|
368
|
+
if (!transport.isAvailable()) {
|
|
369
|
+
this.logger.trace('execute:transport-unavailable', transport.type);
|
|
370
|
+
return tryTransport(index + 1, lastError);
|
|
371
|
+
}
|
|
372
|
+
this.logger.trace('execute:trying', transport.type);
|
|
373
|
+
const preparedCtx = transport.prepareRequest(ctx);
|
|
374
|
+
return transport.execute(preparedCtx, responseType)
|
|
375
|
+
.catch((error) => {
|
|
376
|
+
this.logger.warn('execute:transport-failed', transport.type, error);
|
|
377
|
+
return tryTransport(index + 1, error);
|
|
378
|
+
});
|
|
379
|
+
};
|
|
380
|
+
return tryTransport(0, null);
|
|
381
|
+
}
|
|
382
|
+
validateParams(url, pathParams, data) {
|
|
383
|
+
const matches = url.match(ApiService.PARAM_PATTERN) ?? [];
|
|
384
|
+
for (const match of matches) {
|
|
385
|
+
const paramName = match.slice(1);
|
|
386
|
+
const inPathParams = pathParams !== undefined && paramName in pathParams;
|
|
387
|
+
const inData = data !== undefined && paramName in data;
|
|
388
|
+
if (!inPathParams && !inData) {
|
|
389
|
+
throw new Error(`Missing path param '${match}'`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
genCacheKey(request, ctx) {
|
|
394
|
+
const parts = [
|
|
395
|
+
request.method,
|
|
396
|
+
ctx.url,
|
|
397
|
+
JSON.stringify(ctx.data ?? {}),
|
|
398
|
+
request.pagination?.page ?? 0
|
|
399
|
+
];
|
|
400
|
+
return 'api-cache:' + btoa(parts.join('|')).slice(0, 24);
|
|
401
|
+
}
|
|
402
|
+
getFromCache(request, ctx) {
|
|
403
|
+
const key = this.genCacheKey(request, ctx);
|
|
404
|
+
const storage = request.cache?.storage ?? 'session';
|
|
405
|
+
let entry = null;
|
|
406
|
+
if (storage === 'session') {
|
|
407
|
+
const raw = sessionStorage.getItem(key);
|
|
408
|
+
entry = raw ? JSON.parse(raw) : null;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
entry = this.memoryCache.get(key) ?? null;
|
|
412
|
+
}
|
|
413
|
+
if (!entry) {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
// Check TTL
|
|
417
|
+
if (entry.expires && Date.now() > entry.expires) {
|
|
418
|
+
if (storage === 'session') {
|
|
419
|
+
sessionStorage.removeItem(key);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
this.memoryCache.delete(key);
|
|
423
|
+
}
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
return entry.data;
|
|
427
|
+
}
|
|
428
|
+
storeInCache(request, ctx, response) {
|
|
429
|
+
const key = this.genCacheKey(request, ctx);
|
|
430
|
+
const storage = request.cache?.storage ?? 'session';
|
|
431
|
+
const ttl = request.cache?.ttl;
|
|
432
|
+
const entry = {
|
|
433
|
+
data: response,
|
|
434
|
+
expires: ttl ? Date.now() + (ttl * 1000) : null,
|
|
435
|
+
created: Date.now()
|
|
436
|
+
};
|
|
437
|
+
if (storage === 'session') {
|
|
438
|
+
sessionStorage.setItem(key, JSON.stringify(entry));
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
this.memoryCache.set(key, entry);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
class ApiRequestBuilder {
|
|
446
|
+
api;
|
|
447
|
+
_url;
|
|
448
|
+
_method = 'GET';
|
|
449
|
+
_data;
|
|
450
|
+
_pathParams;
|
|
451
|
+
_queryString = {};
|
|
452
|
+
_headers = {};
|
|
453
|
+
_inputCodecs = [];
|
|
454
|
+
_outputCodecs = [];
|
|
455
|
+
_pagination = null;
|
|
456
|
+
_cache = null;
|
|
457
|
+
_contentType = 'application/json';
|
|
458
|
+
_accept = 'application/json';
|
|
459
|
+
_responseType = 'auto';
|
|
460
|
+
constructor(api, path, pathParams) {
|
|
461
|
+
this.api = api;
|
|
462
|
+
this._url = path;
|
|
463
|
+
this._pathParams = pathParams;
|
|
464
|
+
}
|
|
465
|
+
// Query string
|
|
466
|
+
queryString(params) {
|
|
467
|
+
this._queryString = { ...this._queryString, ...params };
|
|
468
|
+
return this;
|
|
469
|
+
}
|
|
470
|
+
// Format entrée
|
|
471
|
+
fromJson(data) {
|
|
472
|
+
this._contentType = 'application/json';
|
|
473
|
+
if (data !== undefined) {
|
|
474
|
+
this._data = data;
|
|
475
|
+
}
|
|
476
|
+
return this;
|
|
477
|
+
}
|
|
478
|
+
fromForm(data) {
|
|
479
|
+
this._contentType = 'application/x-www-form-urlencoded';
|
|
480
|
+
if (data !== undefined) {
|
|
481
|
+
this._data = data;
|
|
482
|
+
}
|
|
483
|
+
return this;
|
|
484
|
+
}
|
|
485
|
+
fromMultipart(data) {
|
|
486
|
+
this._contentType = 'multipart/form-data';
|
|
487
|
+
if (data !== undefined) {
|
|
488
|
+
this._data = data;
|
|
489
|
+
}
|
|
490
|
+
return this;
|
|
491
|
+
}
|
|
492
|
+
// Format sortie
|
|
493
|
+
toJson() {
|
|
494
|
+
this._accept = 'application/json';
|
|
495
|
+
this._responseType = 'json';
|
|
496
|
+
return this;
|
|
497
|
+
}
|
|
498
|
+
toXls() {
|
|
499
|
+
this._accept = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
500
|
+
this._responseType = 'blob';
|
|
501
|
+
return this;
|
|
502
|
+
}
|
|
503
|
+
toBlob() {
|
|
504
|
+
this._accept = 'application/octet-stream';
|
|
505
|
+
this._responseType = 'blob';
|
|
506
|
+
return this;
|
|
507
|
+
}
|
|
508
|
+
toText() {
|
|
509
|
+
this._accept = 'text/plain';
|
|
510
|
+
this._responseType = 'text';
|
|
511
|
+
return this;
|
|
512
|
+
}
|
|
513
|
+
toArrayBuffer() {
|
|
514
|
+
this._accept = 'application/octet-stream';
|
|
515
|
+
this._responseType = 'arraybuffer';
|
|
516
|
+
return this;
|
|
517
|
+
}
|
|
518
|
+
// Codecs
|
|
519
|
+
withInputCodec(codec) {
|
|
520
|
+
this._inputCodecs.push(codec);
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
withOutputCodec(codec) {
|
|
524
|
+
this._outputCodecs.push(codec);
|
|
525
|
+
return this;
|
|
526
|
+
}
|
|
527
|
+
// Pagination & Cache
|
|
528
|
+
withPagination(config) {
|
|
529
|
+
this._pagination = { pageSize: 20, ...config };
|
|
530
|
+
return this;
|
|
531
|
+
}
|
|
532
|
+
withCache(config) {
|
|
533
|
+
this._cache = { storage: 'session', ...config };
|
|
534
|
+
return this;
|
|
535
|
+
}
|
|
536
|
+
// Execution
|
|
537
|
+
get() {
|
|
538
|
+
this._method = 'GET';
|
|
539
|
+
return this.api.execute(this.build());
|
|
540
|
+
}
|
|
541
|
+
post() {
|
|
542
|
+
this._method = 'POST';
|
|
543
|
+
return this.api.execute(this.build());
|
|
544
|
+
}
|
|
545
|
+
put() {
|
|
546
|
+
this._method = 'PUT';
|
|
547
|
+
return this.api.execute(this.build());
|
|
548
|
+
}
|
|
549
|
+
patch() {
|
|
550
|
+
this._method = 'PATCH';
|
|
551
|
+
return this.api.execute(this.build());
|
|
552
|
+
}
|
|
553
|
+
delete() {
|
|
554
|
+
this._method = 'DELETE';
|
|
555
|
+
return this.api.execute(this.build());
|
|
556
|
+
}
|
|
557
|
+
request(verb) {
|
|
558
|
+
this._method = verb.toUpperCase();
|
|
559
|
+
return this.api.execute(this.build());
|
|
560
|
+
}
|
|
561
|
+
build() {
|
|
562
|
+
return {
|
|
563
|
+
url: this.appendQueryString(this._url),
|
|
564
|
+
method: this._method,
|
|
565
|
+
headers: {
|
|
566
|
+
'Content-Type': this._contentType,
|
|
567
|
+
'Accept': this._accept,
|
|
568
|
+
...this._headers
|
|
569
|
+
},
|
|
570
|
+
data: this._data,
|
|
571
|
+
pathParams: this._pathParams,
|
|
572
|
+
responseType: this._responseType,
|
|
573
|
+
inputCodecs: this._inputCodecs,
|
|
574
|
+
outputCodecs: this._outputCodecs,
|
|
575
|
+
pagination: this._pagination,
|
|
576
|
+
cache: this._cache
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
appendQueryString(url) {
|
|
580
|
+
if (Object.keys(this._queryString).length === 0) {
|
|
581
|
+
return url;
|
|
582
|
+
}
|
|
583
|
+
const params = new URLSearchParams();
|
|
584
|
+
for (const [key, value] of Object.entries(this._queryString)) {
|
|
585
|
+
if (value !== undefined && value !== null) {
|
|
586
|
+
params.append(key, String(value));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
const qs = params.toString();
|
|
590
|
+
if (!qs) {
|
|
591
|
+
return url;
|
|
592
|
+
}
|
|
593
|
+
return url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// io sera chargé à la demande via require()
|
|
598
|
+
let io = null;
|
|
599
|
+
function getSocketIo() {
|
|
600
|
+
if (!io) {
|
|
601
|
+
try {
|
|
602
|
+
io = require('socket.io-client').io;
|
|
603
|
+
}
|
|
604
|
+
catch {
|
|
605
|
+
throw new Error('socket.io-client non installé. ' +
|
|
606
|
+
'Installez-le avec : npm install socket.io-client');
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return io;
|
|
610
|
+
}
|
|
611
|
+
const ISocketioService = DI.createInterface('ISocketioService', (x) => x.singleton(SocketioService));
|
|
612
|
+
class SocketioService {
|
|
613
|
+
logger;
|
|
614
|
+
config;
|
|
615
|
+
type = Transport.Socketio;
|
|
616
|
+
timeout = 5000;
|
|
617
|
+
socket = null;
|
|
618
|
+
connected = false;
|
|
619
|
+
constructor(logger = resolve(ILogger).scopeTo('SocketioService'), config = resolve(IBleetConfiguration)) {
|
|
620
|
+
this.logger = logger;
|
|
621
|
+
this.config = config;
|
|
622
|
+
this.logger.trace('constructor');
|
|
623
|
+
}
|
|
624
|
+
isConnected() {
|
|
625
|
+
return this.connected && this.socket !== null;
|
|
626
|
+
}
|
|
627
|
+
isAvailable() {
|
|
628
|
+
return this.isConnected();
|
|
629
|
+
}
|
|
630
|
+
prepareRequest(ctx) {
|
|
631
|
+
return {
|
|
632
|
+
...ctx,
|
|
633
|
+
data: { ...ctx.data, ...ctx.pathParams }
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
connect(namespace = '/', options) {
|
|
637
|
+
const baseUrl = this.config.getBaseUrl(Transport.Socketio);
|
|
638
|
+
const url = baseUrl + namespace;
|
|
639
|
+
this.logger.trace('connect', url);
|
|
640
|
+
if (this.socket !== null) {
|
|
641
|
+
this.logger.warn('connect:already-connected');
|
|
642
|
+
return Promise.resolve();
|
|
643
|
+
}
|
|
644
|
+
return new Promise((resolve, reject) => {
|
|
645
|
+
const socketIo = getSocketIo();
|
|
646
|
+
this.socket = socketIo(url, {
|
|
647
|
+
transports: ['websocket'],
|
|
648
|
+
...options
|
|
649
|
+
});
|
|
650
|
+
this.socket.on('connect', () => {
|
|
651
|
+
this.logger.trace('connect:success');
|
|
652
|
+
this.connected = true;
|
|
653
|
+
resolve();
|
|
654
|
+
});
|
|
655
|
+
this.socket.on('connect_error', (error) => {
|
|
656
|
+
this.logger.error('connect:error', error);
|
|
657
|
+
this.connected = false;
|
|
658
|
+
reject(error);
|
|
659
|
+
});
|
|
660
|
+
this.socket.on('disconnect', (reason) => {
|
|
661
|
+
this.logger.trace('disconnect', reason);
|
|
662
|
+
this.connected = false;
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
disconnect() {
|
|
667
|
+
this.logger.trace('disconnect');
|
|
668
|
+
if (this.socket !== null) {
|
|
669
|
+
this.socket.disconnect();
|
|
670
|
+
this.socket = null;
|
|
671
|
+
this.connected = false;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
execute(ctx, responseType) {
|
|
675
|
+
this.logger.trace('execute', ctx.method, ctx.url);
|
|
676
|
+
if (!this.isConnected() || this.socket === null) {
|
|
677
|
+
return Promise.reject(new Error('Socket not connected'));
|
|
678
|
+
}
|
|
679
|
+
const channel = `${ctx.method.toLowerCase()}:${ctx.url}`;
|
|
680
|
+
let data = ctx.data ?? {};
|
|
681
|
+
// Convert FormData to plain object (Socket.io can't send FormData)
|
|
682
|
+
if (data instanceof FormData) {
|
|
683
|
+
const obj = {};
|
|
684
|
+
data.forEach((value, key) => {
|
|
685
|
+
// Skip File objects - can't be serialized for Socket.io
|
|
686
|
+
if (!(value instanceof File)) {
|
|
687
|
+
obj[key] = value;
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
data = obj;
|
|
691
|
+
}
|
|
692
|
+
return new Promise((resolve, reject) => {
|
|
693
|
+
const timeoutId = setTimeout(() => {
|
|
694
|
+
reject(new Error('Socket timeout'));
|
|
695
|
+
}, this.timeout);
|
|
696
|
+
this.socket.emit(channel, data, (response) => {
|
|
697
|
+
clearTimeout(timeoutId);
|
|
698
|
+
this.logger.trace('execute:response', channel, response);
|
|
699
|
+
resolve(response);
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const IStorageService = /*@__PURE__*/ DI.createInterface('IStorageService', (x) => x.singleton(StorageService));
|
|
706
|
+
class StorageService {
|
|
707
|
+
logger;
|
|
708
|
+
platform;
|
|
709
|
+
constructor(logger = resolve(ILogger).scopeTo('StorageService'), platform = resolve(IPlatform)) {
|
|
710
|
+
this.logger = logger;
|
|
711
|
+
this.platform = platform;
|
|
712
|
+
this.logger.trace('constructor');
|
|
713
|
+
}
|
|
714
|
+
load(key, def = null) {
|
|
715
|
+
this.logger.trace('load', key);
|
|
716
|
+
const value = localStorage.getItem(key);
|
|
717
|
+
if (value === null) {
|
|
718
|
+
return def;
|
|
719
|
+
}
|
|
720
|
+
return JSON.parse(value);
|
|
721
|
+
}
|
|
722
|
+
save(key, value) {
|
|
723
|
+
this.logger.trace('save', key, value);
|
|
724
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
725
|
+
}
|
|
726
|
+
remove(key) {
|
|
727
|
+
this.logger.trace('remove', key);
|
|
728
|
+
localStorage.removeItem(key);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const ITransitionService = /*@__PURE__*/ DI.createInterface('ITransitionService', (x) => x.singleton(TransitionService));
|
|
733
|
+
class TransitionService {
|
|
734
|
+
logger;
|
|
735
|
+
platform;
|
|
736
|
+
securityTimeout = 2000;
|
|
737
|
+
constructor(logger = resolve(ILogger).scopeTo('TransitionService'), platform = resolve(IPlatform)) {
|
|
738
|
+
this.logger = logger;
|
|
739
|
+
this.platform = platform;
|
|
740
|
+
this.logger.trace('constructor');
|
|
741
|
+
}
|
|
742
|
+
run(element, before, after) {
|
|
743
|
+
let securityTimeout = undefined;
|
|
744
|
+
const endTransition = (evt) => {
|
|
745
|
+
if (securityTimeout !== undefined) {
|
|
746
|
+
this.platform.clearTimeout(securityTimeout);
|
|
747
|
+
securityTimeout = undefined;
|
|
748
|
+
}
|
|
749
|
+
element.removeEventListener('transitionend', endTransition);
|
|
750
|
+
if (after) {
|
|
751
|
+
this.logger.trace('after()');
|
|
752
|
+
after(element);
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
if (before) {
|
|
756
|
+
securityTimeout = this.platform.setTimeout(endTransition, this.securityTimeout);
|
|
757
|
+
element.addEventListener('transitionend', endTransition);
|
|
758
|
+
this.platform.requestAnimationFrame(() => {
|
|
759
|
+
this.logger.trace('before()');
|
|
760
|
+
before(element);
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const ITrapFocusService = /*@__PURE__*/ DI.createInterface('ITrapFocusService', (x) => x.transient(TrapFocusService));
|
|
767
|
+
class TrapFocusService {
|
|
768
|
+
logger;
|
|
769
|
+
platform;
|
|
770
|
+
focusableElementsQuerySelector = '[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"]), [accesskey], summary, canvas, audio, video, details, iframe, [contenteditable]';
|
|
771
|
+
opener = null;
|
|
772
|
+
target = null;
|
|
773
|
+
globalElement = null;
|
|
774
|
+
startCallback = null;
|
|
775
|
+
stopCallback = null;
|
|
776
|
+
focusableElements = [];
|
|
777
|
+
lastFocusedElement = null;
|
|
778
|
+
started = false;
|
|
779
|
+
constructor(logger = resolve(ILogger).scopeTo('TrapFocusService'), platform = resolve(IPlatform)) {
|
|
780
|
+
this.logger = logger;
|
|
781
|
+
this.platform = platform;
|
|
782
|
+
this.logger.trace('constructor');
|
|
783
|
+
}
|
|
784
|
+
buildFocusableElements() {
|
|
785
|
+
this.focusableElements = [];
|
|
786
|
+
const focusableElements = this.target?.querySelectorAll(this.focusableElementsQuerySelector);
|
|
787
|
+
focusableElements?.forEach((element) => {
|
|
788
|
+
const isDisabled = element.hasAttribute('disabled');
|
|
789
|
+
const isAriaHidden = (element.getAttribute('aria-hidden') === 'true');
|
|
790
|
+
const isNotTabbable = (element.getAttribute('tabindex') === '-1');
|
|
791
|
+
if (isDisabled === false && isAriaHidden === false && isNotTabbable === false) {
|
|
792
|
+
this.focusableElements.push(element);
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
start(opener, target, globalElement, startCallback, stopCallback, initialFocusElement) {
|
|
797
|
+
this.logger.trace('start', opener, target);
|
|
798
|
+
this.startCallback = startCallback ?? null;
|
|
799
|
+
this.stopCallback = stopCallback ?? null;
|
|
800
|
+
this.opener = opener;
|
|
801
|
+
this.target = target;
|
|
802
|
+
this.globalElement = globalElement;
|
|
803
|
+
this.buildFocusableElements();
|
|
804
|
+
// Use provided initialFocusElement if valid, otherwise default to first focusable
|
|
805
|
+
if (initialFocusElement && this.focusableElements.includes(initialFocusElement)) {
|
|
806
|
+
this.lastFocusedElement = initialFocusElement;
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
this.lastFocusedElement = this.focusableElements[0] || undefined;
|
|
810
|
+
}
|
|
811
|
+
this.logger.trace('start: add keydown listener');
|
|
812
|
+
this.platform.requestAnimationFrame(() => {
|
|
813
|
+
this.logger.trace('start: focus initial element', this.lastFocusedElement);
|
|
814
|
+
this.lastFocusedElement?.focus();
|
|
815
|
+
});
|
|
816
|
+
this.target.addEventListener('keydown', this.onKeyDown);
|
|
817
|
+
this.platform.document.addEventListener('click', this.onClickOutside);
|
|
818
|
+
this.started = true;
|
|
819
|
+
if (this.startCallback) {
|
|
820
|
+
const promise = this.startCallback();
|
|
821
|
+
if (promise && promise instanceof Promise) {
|
|
822
|
+
return promise;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return Promise.resolve();
|
|
826
|
+
}
|
|
827
|
+
stop() {
|
|
828
|
+
this.logger.trace('stop');
|
|
829
|
+
return new Promise((resolve, reject) => {
|
|
830
|
+
if (this.started) {
|
|
831
|
+
this.logger.trace('stop: remove keydown listener');
|
|
832
|
+
this.target?.removeEventListener('keydown', this.onKeyDown);
|
|
833
|
+
this.platform.document.removeEventListener('click', this.onClickOutside);
|
|
834
|
+
if (this.stopCallback) {
|
|
835
|
+
const promise = this.stopCallback();
|
|
836
|
+
if (promise && promise instanceof Promise) {
|
|
837
|
+
this.platform.requestAnimationFrame(() => {
|
|
838
|
+
this.opener?.focus();
|
|
839
|
+
this.cleanup();
|
|
840
|
+
promise.then((res) => {
|
|
841
|
+
return resolve(res);
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
return resolve(void 0);
|
|
847
|
+
}
|
|
848
|
+
this.platform.requestAnimationFrame(() => {
|
|
849
|
+
this.opener?.focus();
|
|
850
|
+
this.cleanup();
|
|
851
|
+
return resolve(void 0);
|
|
852
|
+
});
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
return reject('TrapFocusService: not started');
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
cleanup() {
|
|
859
|
+
this.logger.trace('cleanup');
|
|
860
|
+
if (this.started) {
|
|
861
|
+
this.opener = null;
|
|
862
|
+
this.startCallback = null;
|
|
863
|
+
this.stopCallback = null;
|
|
864
|
+
this.target = null;
|
|
865
|
+
this.lastFocusedElement = null;
|
|
866
|
+
this.focusableElements = [];
|
|
867
|
+
this.started = false;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
focusedElementIndex() {
|
|
871
|
+
let index = -1;
|
|
872
|
+
if (this.lastFocusedElement) {
|
|
873
|
+
index = this.focusableElements.indexOf(this.lastFocusedElement);
|
|
874
|
+
}
|
|
875
|
+
if (index === -1 && this.lastFocusedElement !== undefined) {
|
|
876
|
+
this.lastFocusedElement = null;
|
|
877
|
+
}
|
|
878
|
+
return index;
|
|
879
|
+
}
|
|
880
|
+
focusPreviousElement(loop = true) {
|
|
881
|
+
const currentIndex = this.focusedElementIndex();
|
|
882
|
+
if (currentIndex === -1) {
|
|
883
|
+
return null;
|
|
884
|
+
}
|
|
885
|
+
let changed = false;
|
|
886
|
+
if (currentIndex === 0 && loop === true) {
|
|
887
|
+
this.lastFocusedElement = this.focusableElements[this.focusableElements.length - 1];
|
|
888
|
+
changed = true;
|
|
889
|
+
}
|
|
890
|
+
else if (currentIndex > 0) {
|
|
891
|
+
this.lastFocusedElement = this.focusableElements[currentIndex - 1];
|
|
892
|
+
changed = true;
|
|
893
|
+
}
|
|
894
|
+
if (changed === true) {
|
|
895
|
+
this.platform.requestAnimationFrame(() => {
|
|
896
|
+
this.logger.trace('focusPreviousElement: focusing', this.lastFocusedElement);
|
|
897
|
+
this.lastFocusedElement?.focus();
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
return this.lastFocusedElement;
|
|
901
|
+
}
|
|
902
|
+
focusNextElement(loop = true) {
|
|
903
|
+
const currentIndex = this.focusedElementIndex();
|
|
904
|
+
if (currentIndex === -1) {
|
|
905
|
+
return null;
|
|
906
|
+
}
|
|
907
|
+
let changed = false;
|
|
908
|
+
if (currentIndex === this.focusableElements.length - 1 && loop === true) {
|
|
909
|
+
this.lastFocusedElement = this.focusableElements[0];
|
|
910
|
+
changed = true;
|
|
911
|
+
}
|
|
912
|
+
else if (currentIndex < this.focusableElements.length - 1) {
|
|
913
|
+
this.lastFocusedElement = this.focusableElements[currentIndex + 1];
|
|
914
|
+
changed = true;
|
|
915
|
+
}
|
|
916
|
+
if (changed === true) {
|
|
917
|
+
this.platform.requestAnimationFrame(() => {
|
|
918
|
+
this.logger.trace('focusNextElement: focusing', this.lastFocusedElement);
|
|
919
|
+
this.lastFocusedElement?.focus();
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
return this.lastFocusedElement;
|
|
923
|
+
}
|
|
924
|
+
onKeyDown = (event) => {
|
|
925
|
+
if (event.key === 'Tab') {
|
|
926
|
+
if (event.shiftKey) {
|
|
927
|
+
// shift + tab loop backwards
|
|
928
|
+
event.preventDefault();
|
|
929
|
+
this.lastFocusedElement = this.focusPreviousElement(true);
|
|
930
|
+
}
|
|
931
|
+
else {
|
|
932
|
+
// tab loop forwards
|
|
933
|
+
event.preventDefault();
|
|
934
|
+
this.lastFocusedElement = this.focusNextElement(true);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
else if (event.key === 'ArrowUp') {
|
|
938
|
+
// up arrow, no loop
|
|
939
|
+
event.preventDefault();
|
|
940
|
+
this.lastFocusedElement = this.focusPreviousElement(false);
|
|
941
|
+
}
|
|
942
|
+
else if (event.key === 'ArrowDown') {
|
|
943
|
+
// down arrow, no loop
|
|
944
|
+
event.preventDefault();
|
|
945
|
+
this.lastFocusedElement = this.focusNextElement(false);
|
|
946
|
+
}
|
|
947
|
+
else if (event.key === 'Escape') {
|
|
948
|
+
// stop trap focus
|
|
949
|
+
event.preventDefault();
|
|
950
|
+
this.stop();
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
onClickOutside = (event) => {
|
|
954
|
+
this.logger.trace('onClickOutside', event);
|
|
955
|
+
if (this.started && this.globalElement && event.target) {
|
|
956
|
+
this.logger.trace('onClickOutside: checking if click is outside globalElement', event.target, this.globalElement);
|
|
957
|
+
if (!this.globalElement.contains(event.target)) {
|
|
958
|
+
this.stop();
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/******************************************************************************
|
|
965
|
+
Copyright (c) Microsoft Corporation.
|
|
966
|
+
|
|
967
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
968
|
+
purpose with or without fee is hereby granted.
|
|
969
|
+
|
|
970
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
971
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
972
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
973
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
974
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
975
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
976
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
977
|
+
***************************************************************************** */
|
|
978
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
982
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
983
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
984
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
985
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
986
|
+
var _, done = false;
|
|
987
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
988
|
+
var context = {};
|
|
989
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
990
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
991
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
992
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
993
|
+
if (kind === "accessor") {
|
|
994
|
+
if (result === void 0) continue;
|
|
995
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
996
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
997
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
998
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
999
|
+
}
|
|
1000
|
+
else if (_ = accept(result)) {
|
|
1001
|
+
if (kind === "field") initializers.unshift(_);
|
|
1002
|
+
else descriptor[key] = _;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
1006
|
+
done = true;
|
|
1007
|
+
}
|
|
1008
|
+
function __runInitializers(thisArg, initializers, value) {
|
|
1009
|
+
var useValue = arguments.length > 2;
|
|
1010
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
1011
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
1012
|
+
}
|
|
1013
|
+
return useValue ? value : void 0;
|
|
1014
|
+
}
|
|
1015
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1016
|
+
var e = new Error(message);
|
|
1017
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
var Channels;
|
|
1021
|
+
(function (Channels) {
|
|
1022
|
+
Channels["Overlay"] = "bleet:overlay";
|
|
1023
|
+
Channels["OverlayStatus"] = "bleet:overlay:status";
|
|
1024
|
+
Channels["Modal"] = "bleet:modal";
|
|
1025
|
+
Channels["ModalStatus"] = "bleet:modal:status";
|
|
1026
|
+
Channels["Drawer"] = "bleet:drawer";
|
|
1027
|
+
Channels["DrawerStatus"] = "bleet:drawer:status";
|
|
1028
|
+
Channels["Toaster"] = "bleet:toaster";
|
|
1029
|
+
Channels["ToasterStatus"] = "bleet:toaster:status";
|
|
1030
|
+
Channels["Menu"] = "bleet:menu";
|
|
1031
|
+
Channels["MenuStatus"] = "bleet:menu:status";
|
|
1032
|
+
Channels["Badge"] = "bleet:badge";
|
|
1033
|
+
Channels["Profile"] = "bleet:profile";
|
|
1034
|
+
Channels["ProfileStatus"] = "bleet:profile:status";
|
|
1035
|
+
Channels["Ajaxify"] = "bleet:ajaxify";
|
|
1036
|
+
})(Channels || (Channels = {}));
|
|
1037
|
+
var OverlayAction;
|
|
1038
|
+
(function (OverlayAction) {
|
|
1039
|
+
OverlayAction["Open"] = "open";
|
|
1040
|
+
OverlayAction["Close"] = "close";
|
|
1041
|
+
OverlayAction["Toggle"] = "toggle";
|
|
1042
|
+
})(OverlayAction || (OverlayAction = {}));
|
|
1043
|
+
var OverlayStatus;
|
|
1044
|
+
(function (OverlayStatus) {
|
|
1045
|
+
OverlayStatus["Opening"] = "opening";
|
|
1046
|
+
OverlayStatus["Closing"] = "closing";
|
|
1047
|
+
OverlayStatus["Opened"] = "opened";
|
|
1048
|
+
OverlayStatus["Closed"] = "closed";
|
|
1049
|
+
})(OverlayStatus || (OverlayStatus = {}));
|
|
1050
|
+
var ProfileAction;
|
|
1051
|
+
(function (ProfileAction) {
|
|
1052
|
+
ProfileAction["Open"] = "open";
|
|
1053
|
+
ProfileAction["Close"] = "close";
|
|
1054
|
+
ProfileAction["Toggle"] = "toggle";
|
|
1055
|
+
})(ProfileAction || (ProfileAction = {}));
|
|
1056
|
+
var ProfileStatus;
|
|
1057
|
+
(function (ProfileStatus) {
|
|
1058
|
+
ProfileStatus["Opening"] = "opening";
|
|
1059
|
+
ProfileStatus["Closing"] = "closing";
|
|
1060
|
+
ProfileStatus["Opened"] = "opened";
|
|
1061
|
+
ProfileStatus["Closed"] = "closed";
|
|
1062
|
+
})(ProfileStatus || (ProfileStatus = {}));
|
|
1063
|
+
var ModalAction;
|
|
1064
|
+
(function (ModalAction) {
|
|
1065
|
+
ModalAction["Open"] = "open";
|
|
1066
|
+
ModalAction["Close"] = "close";
|
|
1067
|
+
ModalAction["Toggle"] = "toggle";
|
|
1068
|
+
})(ModalAction || (ModalAction = {}));
|
|
1069
|
+
var ModalStatus;
|
|
1070
|
+
(function (ModalStatus) {
|
|
1071
|
+
ModalStatus["Opening"] = "opening";
|
|
1072
|
+
ModalStatus["Closing"] = "closing";
|
|
1073
|
+
ModalStatus["Opened"] = "opened";
|
|
1074
|
+
ModalStatus["Closed"] = "closed";
|
|
1075
|
+
})(ModalStatus || (ModalStatus = {}));
|
|
1076
|
+
var DrawerAction;
|
|
1077
|
+
(function (DrawerAction) {
|
|
1078
|
+
DrawerAction["Open"] = "open";
|
|
1079
|
+
DrawerAction["Close"] = "close";
|
|
1080
|
+
DrawerAction["Toggle"] = "toggle";
|
|
1081
|
+
})(DrawerAction || (DrawerAction = {}));
|
|
1082
|
+
var DrawerStatus;
|
|
1083
|
+
(function (DrawerStatus) {
|
|
1084
|
+
DrawerStatus["Opening"] = "opening";
|
|
1085
|
+
DrawerStatus["Closing"] = "closing";
|
|
1086
|
+
DrawerStatus["Opened"] = "opened";
|
|
1087
|
+
DrawerStatus["Closed"] = "closed";
|
|
1088
|
+
})(DrawerStatus || (DrawerStatus = {}));
|
|
1089
|
+
var AjaxifyAction;
|
|
1090
|
+
(function (AjaxifyAction) {
|
|
1091
|
+
AjaxifyAction["Refresh"] = "refresh";
|
|
1092
|
+
})(AjaxifyAction || (AjaxifyAction = {}));
|
|
1093
|
+
var ToasterAction;
|
|
1094
|
+
(function (ToasterAction) {
|
|
1095
|
+
ToasterAction["Add"] = "add";
|
|
1096
|
+
ToasterAction["Remove"] = "remove";
|
|
1097
|
+
})(ToasterAction || (ToasterAction = {}));
|
|
1098
|
+
var ToasterStatus;
|
|
1099
|
+
(function (ToasterStatus) {
|
|
1100
|
+
ToasterStatus["Added"] = "added";
|
|
1101
|
+
ToasterStatus["Removed"] = "removed";
|
|
1102
|
+
})(ToasterStatus || (ToasterStatus = {}));
|
|
1103
|
+
var MenuAction;
|
|
1104
|
+
(function (MenuAction) {
|
|
1105
|
+
MenuAction["Open"] = "open";
|
|
1106
|
+
MenuAction["Close"] = "close";
|
|
1107
|
+
MenuAction["Toggle"] = "toggle";
|
|
1108
|
+
})(MenuAction || (MenuAction = {}));
|
|
1109
|
+
var BadgeAction;
|
|
1110
|
+
(function (BadgeAction) {
|
|
1111
|
+
BadgeAction["Remove"] = "remove";
|
|
1112
|
+
})(BadgeAction || (BadgeAction = {}));
|
|
1113
|
+
var MenuStatus;
|
|
1114
|
+
(function (MenuStatus) {
|
|
1115
|
+
MenuStatus["Opening"] = "opening";
|
|
1116
|
+
MenuStatus["Closing"] = "closing";
|
|
1117
|
+
MenuStatus["Opened"] = "opened";
|
|
1118
|
+
MenuStatus["Closed"] = "closed";
|
|
1119
|
+
})(MenuStatus || (MenuStatus = {}));
|
|
1120
|
+
var UiColor;
|
|
1121
|
+
(function (UiColor) {
|
|
1122
|
+
UiColor["Primary"] = "primary";
|
|
1123
|
+
UiColor["Secondary"] = "secondary";
|
|
1124
|
+
UiColor["Success"] = "success";
|
|
1125
|
+
UiColor["Danger"] = "danger";
|
|
1126
|
+
UiColor["Warning"] = "warning";
|
|
1127
|
+
UiColor["Info"] = "info";
|
|
1128
|
+
UiColor["Accent"] = "accent";
|
|
1129
|
+
})(UiColor || (UiColor = {}));
|
|
1130
|
+
var UiToastIcon;
|
|
1131
|
+
(function (UiToastIcon) {
|
|
1132
|
+
UiToastIcon["Info"] = "information-circle";
|
|
1133
|
+
UiToastIcon["Success"] = "check-circle";
|
|
1134
|
+
UiToastIcon["Warning"] = "exclamation-triangle";
|
|
1135
|
+
UiToastIcon["Danger"] = "x-circle";
|
|
1136
|
+
})(UiToastIcon || (UiToastIcon = {}));
|
|
1137
|
+
/**
|
|
1138
|
+
* Icônes pour toasts et dialogs
|
|
1139
|
+
* Double alias : court (Info) et long (InformationCircle) → même valeur
|
|
1140
|
+
*/
|
|
1141
|
+
var UiIcon;
|
|
1142
|
+
(function (UiIcon) {
|
|
1143
|
+
// Alias courts (usage dev)
|
|
1144
|
+
UiIcon["Info"] = "information-circle";
|
|
1145
|
+
UiIcon["Success"] = "check-circle";
|
|
1146
|
+
UiIcon["Warning"] = "exclamation-triangle";
|
|
1147
|
+
UiIcon["Danger"] = "x-circle";
|
|
1148
|
+
// Alias longs (match heroicon)
|
|
1149
|
+
UiIcon["InformationCircle"] = "information-circle";
|
|
1150
|
+
UiIcon["CheckCircle"] = "check-circle";
|
|
1151
|
+
UiIcon["ExclamationTriangle"] = "exclamation-triangle";
|
|
1152
|
+
UiIcon["XCircle"] = "x-circle";
|
|
1153
|
+
})(UiIcon || (UiIcon = {}));
|
|
1154
|
+
/**
|
|
1155
|
+
* Actions primaires dialog (mutuellement exclusives)
|
|
1156
|
+
*/
|
|
1157
|
+
var DialogAction;
|
|
1158
|
+
(function (DialogAction) {
|
|
1159
|
+
DialogAction["Keep"] = "keep";
|
|
1160
|
+
DialogAction["Close"] = "close";
|
|
1161
|
+
DialogAction["RefreshAndClose"] = "refreshAndClose";
|
|
1162
|
+
})(DialogAction || (DialogAction = {}));
|
|
1163
|
+
|
|
1164
|
+
let BleetBurgerCustomAttribute = (() => {
|
|
1165
|
+
let _classDecorators = [customAttribute('bleet-burger')];
|
|
1166
|
+
let _classDescriptor;
|
|
1167
|
+
let _classExtraInitializers = [];
|
|
1168
|
+
let _classThis;
|
|
1169
|
+
(class {
|
|
1170
|
+
static { _classThis = this; }
|
|
1171
|
+
static {
|
|
1172
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1173
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1174
|
+
_classThis = _classDescriptor.value;
|
|
1175
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1176
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1177
|
+
}
|
|
1178
|
+
logger;
|
|
1179
|
+
ea;
|
|
1180
|
+
element;
|
|
1181
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-burger'), ea = resolve(IEventAggregator), element = resolve(INode)) {
|
|
1182
|
+
this.logger = logger;
|
|
1183
|
+
this.ea = ea;
|
|
1184
|
+
this.element = element;
|
|
1185
|
+
this.logger.trace('constructor');
|
|
1186
|
+
}
|
|
1187
|
+
attached() {
|
|
1188
|
+
this.logger.trace('attached');
|
|
1189
|
+
this.element.addEventListener('click', this.onClickButton);
|
|
1190
|
+
}
|
|
1191
|
+
detached() {
|
|
1192
|
+
this.logger.trace('detached');
|
|
1193
|
+
this.element.removeEventListener('click', this.onClickButton);
|
|
1194
|
+
}
|
|
1195
|
+
onClickButton = (event) => {
|
|
1196
|
+
this.logger.trace('onClickButton', event);
|
|
1197
|
+
event.preventDefault();
|
|
1198
|
+
this.ea.publish(Channels.Menu, { action: MenuAction.Open });
|
|
1199
|
+
};
|
|
1200
|
+
});
|
|
1201
|
+
return _classThis;
|
|
1202
|
+
})();
|
|
1203
|
+
|
|
1204
|
+
let BleetMenuCustomAttribute = (() => {
|
|
1205
|
+
let _classDecorators = [customAttribute('bleet-menu')];
|
|
1206
|
+
let _classDescriptor;
|
|
1207
|
+
let _classExtraInitializers = [];
|
|
1208
|
+
let _classThis;
|
|
1209
|
+
(class {
|
|
1210
|
+
static { _classThis = this; }
|
|
1211
|
+
static {
|
|
1212
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1213
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1214
|
+
_classThis = _classDescriptor.value;
|
|
1215
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1216
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1217
|
+
}
|
|
1218
|
+
logger;
|
|
1219
|
+
ea;
|
|
1220
|
+
element;
|
|
1221
|
+
platform;
|
|
1222
|
+
transitionService;
|
|
1223
|
+
storageService;
|
|
1224
|
+
disposable;
|
|
1225
|
+
disposableOverlay;
|
|
1226
|
+
closeButton;
|
|
1227
|
+
toggleButtons;
|
|
1228
|
+
sublists = new Map();
|
|
1229
|
+
isOpen = false;
|
|
1230
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-menu'), ea = resolve(IEventAggregator), element = resolve(INode), platform = resolve(IPlatform), transitionService = resolve(ITransitionService), storageService = resolve(IStorageService)) {
|
|
1231
|
+
this.logger = logger;
|
|
1232
|
+
this.ea = ea;
|
|
1233
|
+
this.element = element;
|
|
1234
|
+
this.platform = platform;
|
|
1235
|
+
this.transitionService = transitionService;
|
|
1236
|
+
this.storageService = storageService;
|
|
1237
|
+
this.logger.trace('constructor');
|
|
1238
|
+
}
|
|
1239
|
+
attaching() {
|
|
1240
|
+
this.logger.trace('attaching');
|
|
1241
|
+
this.closeButton = this.element.querySelector('[data-menu=close]');
|
|
1242
|
+
this.toggleButtons = this.element.querySelectorAll('[data-menu^="toggle-button"]');
|
|
1243
|
+
this.initMenuButtons();
|
|
1244
|
+
}
|
|
1245
|
+
attached() {
|
|
1246
|
+
this.logger.trace('attached');
|
|
1247
|
+
this.disposable = this.ea.subscribe(Channels.Menu, this.onMenuEvent);
|
|
1248
|
+
this.disposableOverlay = this.ea.subscribe(Channels.OverlayStatus, this.onOverlayStatus);
|
|
1249
|
+
this.closeButton?.addEventListener('click', this.onClickClose);
|
|
1250
|
+
this.element.addEventListener('click', this.onClickToggleButtons);
|
|
1251
|
+
}
|
|
1252
|
+
detached() {
|
|
1253
|
+
this.logger.trace('detached');
|
|
1254
|
+
this.closeButton?.removeEventListener('click', this.onClickClose);
|
|
1255
|
+
this.element.removeEventListener('click', this.onClickToggleButtons);
|
|
1256
|
+
this.disposableOverlay?.dispose();
|
|
1257
|
+
this.disposable?.dispose();
|
|
1258
|
+
}
|
|
1259
|
+
dispose() {
|
|
1260
|
+
this.logger.trace('dispose');
|
|
1261
|
+
this.disposableOverlay?.dispose();
|
|
1262
|
+
this.disposable?.dispose();
|
|
1263
|
+
}
|
|
1264
|
+
open(fromOverlay = false) {
|
|
1265
|
+
if (!this.isOpen) {
|
|
1266
|
+
this.logger.trace('open');
|
|
1267
|
+
this.isOpen = true;
|
|
1268
|
+
this.transitionService.run(this.element, (element) => {
|
|
1269
|
+
if (!fromOverlay) {
|
|
1270
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Open });
|
|
1271
|
+
}
|
|
1272
|
+
this.ea.publish(Channels.MenuStatus, { status: MenuStatus.Opening });
|
|
1273
|
+
element.classList.add('translate-x-0');
|
|
1274
|
+
element.classList.remove('-translate-x-full');
|
|
1275
|
+
element.ariaHidden = 'false';
|
|
1276
|
+
}, (element) => {
|
|
1277
|
+
this.ea.publish(Channels.MenuStatus, { status: MenuStatus.Opened });
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
close(fromOverlay = false) {
|
|
1282
|
+
if (this.isOpen) {
|
|
1283
|
+
this.logger.trace('close');
|
|
1284
|
+
this.isOpen = false;
|
|
1285
|
+
this.transitionService.run(this.element, (element) => {
|
|
1286
|
+
this.ea.publish(Channels.MenuStatus, { status: MenuStatus.Closing });
|
|
1287
|
+
if (!fromOverlay) {
|
|
1288
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
1289
|
+
}
|
|
1290
|
+
element.classList.add('-translate-x-full');
|
|
1291
|
+
element.classList.remove('translate-x-0');
|
|
1292
|
+
element.ariaHidden = 'true';
|
|
1293
|
+
}, (element) => {
|
|
1294
|
+
this.ea.publish(Channels.MenuStatus, { status: MenuStatus.Closed });
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
onClickClose = (event) => {
|
|
1299
|
+
this.logger.trace('onClickClose', event);
|
|
1300
|
+
event.preventDefault();
|
|
1301
|
+
this.close();
|
|
1302
|
+
};
|
|
1303
|
+
onClickToggleButtons = (event) => {
|
|
1304
|
+
const target = event.target;
|
|
1305
|
+
const btn = target.closest('[data-menu^="toggle-button"]');
|
|
1306
|
+
if (btn && btn.matches('[data-menu^="toggle-button"]')) {
|
|
1307
|
+
event.preventDefault();
|
|
1308
|
+
this.toggleButton(btn);
|
|
1309
|
+
}
|
|
1310
|
+
};
|
|
1311
|
+
initMenuButtons() {
|
|
1312
|
+
this.logger.trace('initMenu');
|
|
1313
|
+
this.toggleButtons?.forEach((btn) => {
|
|
1314
|
+
if (!this.sublists.has(btn)) {
|
|
1315
|
+
const id = btn.dataset.menu?.replace('toggle-button-', '');
|
|
1316
|
+
const isOpen = this.storageService.load(`toggle-list-${id}`, false);
|
|
1317
|
+
const list = this.element.querySelector(`[data-menu="toggle-list-${id}"]`);
|
|
1318
|
+
const svg = btn.querySelector('svg[data-menu=icon]');
|
|
1319
|
+
this.sublists.set(btn, { list, svg });
|
|
1320
|
+
if (!isOpen) {
|
|
1321
|
+
svg.classList.remove('rotate-180');
|
|
1322
|
+
list.classList.add('hidden');
|
|
1323
|
+
btn.ariaExpanded = 'false';
|
|
1324
|
+
}
|
|
1325
|
+
else {
|
|
1326
|
+
svg.classList.add('rotate-180');
|
|
1327
|
+
list.classList.remove('hidden');
|
|
1328
|
+
btn.ariaExpanded = 'true';
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
toggleButton(btn) {
|
|
1334
|
+
if (this.sublists.has(btn)) {
|
|
1335
|
+
const sublist = this.sublists.get(btn);
|
|
1336
|
+
const id = btn.dataset.menu?.replace('toggle-button-', '');
|
|
1337
|
+
if (sublist?.list.classList.contains('hidden')) {
|
|
1338
|
+
sublist?.list.classList.remove('hidden');
|
|
1339
|
+
sublist?.svg.classList.add('rotate-180');
|
|
1340
|
+
btn.ariaExpanded = 'true';
|
|
1341
|
+
this.storageService.save(`toggle-list-${id}`, true);
|
|
1342
|
+
}
|
|
1343
|
+
else {
|
|
1344
|
+
sublist?.list.classList.add('hidden');
|
|
1345
|
+
sublist?.svg.classList.remove('rotate-180');
|
|
1346
|
+
btn.ariaExpanded = 'false';
|
|
1347
|
+
this.storageService.save(`toggle-list-${id}`, false);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
closeOtherButtons(except) {
|
|
1352
|
+
this.sublists.forEach((value, key) => {
|
|
1353
|
+
if (key !== except) {
|
|
1354
|
+
const id = key.dataset.menu?.replace('toggle-button-', '');
|
|
1355
|
+
this.storageService.save(`toggle-list-${id}`, false);
|
|
1356
|
+
value.list.classList.add('hidden');
|
|
1357
|
+
value.svg.classList.remove('rotate-180');
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
onMenuEvent = (data) => {
|
|
1362
|
+
this.logger.trace('onMenuEvent', data);
|
|
1363
|
+
if (data.action === MenuAction.Close) {
|
|
1364
|
+
// this.element.classList.add('-translate-x-full');
|
|
1365
|
+
this.logger.trace('Menu Close action received');
|
|
1366
|
+
this.close();
|
|
1367
|
+
}
|
|
1368
|
+
else if (data.action === MenuAction.Open) {
|
|
1369
|
+
// this.element.classList.remove('-translate-x-full');
|
|
1370
|
+
this.logger.trace('Menu Open action received');
|
|
1371
|
+
this.open();
|
|
1372
|
+
}
|
|
1373
|
+
else if (data.action === MenuAction.Toggle) {
|
|
1374
|
+
// this.element.classList.toggle('-translate-x-full');
|
|
1375
|
+
this.logger.trace('Menu Toggle action received');
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
onOverlayStatus = (data) => {
|
|
1379
|
+
if (data.status === OverlayStatus.Closing) {
|
|
1380
|
+
this.logger.trace('Overlay Close action received');
|
|
1381
|
+
this.close(true);
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
this.logger.trace('onOverlayStatus unhandled', data);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
});
|
|
1388
|
+
return _classThis;
|
|
1389
|
+
})();
|
|
1390
|
+
|
|
1391
|
+
let BleetBadgeCustomAttribute = (() => {
|
|
1392
|
+
let _classDecorators = [customAttribute({ name: 'bleet-badge', defaultProperty: 'id' })];
|
|
1393
|
+
let _classDescriptor;
|
|
1394
|
+
let _classExtraInitializers = [];
|
|
1395
|
+
let _classThis;
|
|
1396
|
+
let _id_decorators;
|
|
1397
|
+
let _id_initializers = [];
|
|
1398
|
+
let _id_extraInitializers = [];
|
|
1399
|
+
(class {
|
|
1400
|
+
static { _classThis = this; }
|
|
1401
|
+
static {
|
|
1402
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1403
|
+
_id_decorators = [bindable];
|
|
1404
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
1405
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1406
|
+
_classThis = _classDescriptor.value;
|
|
1407
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1408
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1409
|
+
}
|
|
1410
|
+
logger;
|
|
1411
|
+
ea;
|
|
1412
|
+
element;
|
|
1413
|
+
closeButton;
|
|
1414
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
1415
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-badge'), ea = resolve(IEventAggregator), element = resolve(INode)) {
|
|
1416
|
+
this.logger = logger;
|
|
1417
|
+
this.ea = ea;
|
|
1418
|
+
this.element = element;
|
|
1419
|
+
this.logger.trace('constructor');
|
|
1420
|
+
}
|
|
1421
|
+
attached() {
|
|
1422
|
+
this.logger.trace('attached');
|
|
1423
|
+
this.closeButton = this.element.querySelector('[data-badge=remove]') ?? undefined;
|
|
1424
|
+
this.closeButton?.addEventListener('click', this.onClickRemove);
|
|
1425
|
+
}
|
|
1426
|
+
detached() {
|
|
1427
|
+
this.logger.trace('detached');
|
|
1428
|
+
this.closeButton?.removeEventListener('click', this.onClickRemove);
|
|
1429
|
+
}
|
|
1430
|
+
onClickRemove = (__runInitializers(this, _id_extraInitializers), (event) => {
|
|
1431
|
+
this.logger.trace('onClickRemove', event);
|
|
1432
|
+
event.preventDefault();
|
|
1433
|
+
this.ea.publish(Channels.Badge, { action: BadgeAction.Remove, id: this.id });
|
|
1434
|
+
this.element.remove();
|
|
1435
|
+
});
|
|
1436
|
+
});
|
|
1437
|
+
return _classThis;
|
|
1438
|
+
})();
|
|
1439
|
+
|
|
1440
|
+
// @ts-ignore
|
|
1441
|
+
let BleetSelectCustomAttribute = (() => {
|
|
1442
|
+
let _classDecorators = [customAttribute('bleet-select')];
|
|
1443
|
+
let _classDescriptor;
|
|
1444
|
+
let _classExtraInitializers = [];
|
|
1445
|
+
let _classThis;
|
|
1446
|
+
(class {
|
|
1447
|
+
static { _classThis = this; }
|
|
1448
|
+
static {
|
|
1449
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1450
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1451
|
+
_classThis = _classDescriptor.value;
|
|
1452
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1453
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1454
|
+
}
|
|
1455
|
+
logger;
|
|
1456
|
+
element;
|
|
1457
|
+
trapFocusService;
|
|
1458
|
+
select;
|
|
1459
|
+
button;
|
|
1460
|
+
buttonText;
|
|
1461
|
+
optionTemplate;
|
|
1462
|
+
itemsPlace;
|
|
1463
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-select'), element = resolve(INode), trapFocusService = resolve(ITrapFocusService)) {
|
|
1464
|
+
this.logger = logger;
|
|
1465
|
+
this.element = element;
|
|
1466
|
+
this.trapFocusService = trapFocusService;
|
|
1467
|
+
this.logger.trace('constructor');
|
|
1468
|
+
}
|
|
1469
|
+
attaching() {
|
|
1470
|
+
this.logger.trace('attaching');
|
|
1471
|
+
this.select = this.element.querySelector('select');
|
|
1472
|
+
this.button = this.element.querySelector('button');
|
|
1473
|
+
this.buttonText = this.button.querySelector('[data-select=value]');
|
|
1474
|
+
this.optionTemplate = this.element.querySelector('[data-select=item-template]');
|
|
1475
|
+
this.itemsPlace = this.element.querySelector('[data-select=items]');
|
|
1476
|
+
}
|
|
1477
|
+
attached() {
|
|
1478
|
+
this.logger.trace('attached');
|
|
1479
|
+
if (!this.itemsPlace) {
|
|
1480
|
+
throw new Error('Items place element not found');
|
|
1481
|
+
}
|
|
1482
|
+
if (!this.itemsPlace.id) {
|
|
1483
|
+
this.itemsPlace.id = `data-select-items-${Math.random().toString(36).substring(2, 15)}`;
|
|
1484
|
+
}
|
|
1485
|
+
if (!this.select?.options) {
|
|
1486
|
+
throw new Error('Select options not found');
|
|
1487
|
+
}
|
|
1488
|
+
if (!this.optionTemplate) {
|
|
1489
|
+
throw new Error('Option template not found');
|
|
1490
|
+
}
|
|
1491
|
+
if (!this.button) {
|
|
1492
|
+
throw new Error('Button element not found');
|
|
1493
|
+
}
|
|
1494
|
+
if (!this.buttonText) {
|
|
1495
|
+
throw new Error('Button text element not found');
|
|
1496
|
+
}
|
|
1497
|
+
this.preparePanel();
|
|
1498
|
+
// ARIA setup
|
|
1499
|
+
this.button.ariaHasPopup = 'listbox';
|
|
1500
|
+
this.button.setAttribute('aria-controls', this.itemsPlace.id);
|
|
1501
|
+
this.itemsPlace.role = 'listbox';
|
|
1502
|
+
// Event listeners
|
|
1503
|
+
this.button?.addEventListener('click', this.onClickToggleMenu);
|
|
1504
|
+
this.itemsPlace?.addEventListener('click', this.onClickToggleItem);
|
|
1505
|
+
}
|
|
1506
|
+
detached() {
|
|
1507
|
+
this.logger.trace('detached');
|
|
1508
|
+
this.button?.removeEventListener('click', this.onClickToggleMenu);
|
|
1509
|
+
this.itemsPlace?.removeEventListener('click', this.onClickToggleItem);
|
|
1510
|
+
}
|
|
1511
|
+
onClickToggleMenu = (event) => {
|
|
1512
|
+
this.logger.trace('onClick', event);
|
|
1513
|
+
event.preventDefault();
|
|
1514
|
+
if (this.select?.disabled) {
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
return this.toggleMenu();
|
|
1518
|
+
};
|
|
1519
|
+
onStopTrapFocus = () => {
|
|
1520
|
+
this.logger.trace('onStopTrapFocus');
|
|
1521
|
+
this.itemsPlace?.classList.add('hidden');
|
|
1522
|
+
return Promise.resolve();
|
|
1523
|
+
};
|
|
1524
|
+
toggleMenu = () => {
|
|
1525
|
+
const isClosed = this.itemsPlace?.classList.contains('hidden');
|
|
1526
|
+
return new Promise((resolve) => {
|
|
1527
|
+
if (isClosed) {
|
|
1528
|
+
// Opening menu
|
|
1529
|
+
this.button.ariaExpanded = 'true';
|
|
1530
|
+
// Find selected option to focus initially
|
|
1531
|
+
const selectedOption = this.itemsPlace?.querySelector('[aria-selected="true"]');
|
|
1532
|
+
return this.trapFocusService.start(this.button, this.itemsPlace, this.element, undefined, this.onStopTrapFocus, selectedOption // Pass selected option as initial focus
|
|
1533
|
+
)
|
|
1534
|
+
.then(() => {
|
|
1535
|
+
this.logger.trace('toggleMenu opened');
|
|
1536
|
+
this.itemsPlace?.classList.remove('hidden');
|
|
1537
|
+
resolve(void 0);
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
else {
|
|
1541
|
+
// Closing menu
|
|
1542
|
+
this.button.ariaExpanded = 'false';
|
|
1543
|
+
return this.trapFocusService.stop()
|
|
1544
|
+
.then(() => {
|
|
1545
|
+
this.logger.trace('toggleMenu closed');
|
|
1546
|
+
this.itemsPlace?.classList.add('hidden');
|
|
1547
|
+
resolve(void 0);
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
});
|
|
1551
|
+
};
|
|
1552
|
+
onClickToggleItem = (event) => {
|
|
1553
|
+
this.logger.trace('onClickItem', event);
|
|
1554
|
+
event.preventDefault();
|
|
1555
|
+
const element = event.target.closest('[data-value]');
|
|
1556
|
+
// Update select options
|
|
1557
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1558
|
+
option.selected = option.value == element.dataset.value;
|
|
1559
|
+
});
|
|
1560
|
+
// Dispatch change event sur le select natif pour active-form
|
|
1561
|
+
this.select?.dispatchEvent(new Event('change', { bubbles: true }));
|
|
1562
|
+
this.synchSelect();
|
|
1563
|
+
};
|
|
1564
|
+
synchSelect() {
|
|
1565
|
+
this.swapItemClasses();
|
|
1566
|
+
// Close menu
|
|
1567
|
+
return this.toggleMenu();
|
|
1568
|
+
}
|
|
1569
|
+
swapItemClasses() {
|
|
1570
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1571
|
+
const item = this.itemsPlace?.querySelector(`[data-value="${option.value}"]`);
|
|
1572
|
+
if (!item)
|
|
1573
|
+
return;
|
|
1574
|
+
const checkmark = item.querySelector('[data-select=item-check]');
|
|
1575
|
+
// Récupérer les classes depuis les data-attributes de l'élément
|
|
1576
|
+
const itemInactiveClasses = item.dataset.classInactive?.split(' ') || [];
|
|
1577
|
+
const itemActiveClasses = item.dataset.classActive?.split(' ') || [];
|
|
1578
|
+
const checkInactiveClasses = checkmark?.dataset.classInactive?.split(' ') || [];
|
|
1579
|
+
const checkActiveClasses = checkmark?.dataset.classActive?.split(' ') || [];
|
|
1580
|
+
if (option.selected) {
|
|
1581
|
+
// Swap vers active
|
|
1582
|
+
item.classList.remove(...itemInactiveClasses);
|
|
1583
|
+
item.classList.add(...itemActiveClasses);
|
|
1584
|
+
checkmark?.classList.remove(...checkInactiveClasses);
|
|
1585
|
+
checkmark?.classList.add(...checkActiveClasses);
|
|
1586
|
+
// Update ARIA
|
|
1587
|
+
item.setAttribute('aria-selected', 'true');
|
|
1588
|
+
this.button?.setAttribute('aria-activedescendant', item.id);
|
|
1589
|
+
// Update button text
|
|
1590
|
+
this.buttonText.innerHTML = option.innerHTML;
|
|
1591
|
+
}
|
|
1592
|
+
else {
|
|
1593
|
+
// Swap vers inactive
|
|
1594
|
+
item.classList.remove(...itemActiveClasses);
|
|
1595
|
+
item.classList.add(...itemInactiveClasses);
|
|
1596
|
+
checkmark?.classList.remove(...checkActiveClasses);
|
|
1597
|
+
checkmark?.classList.add(...checkInactiveClasses);
|
|
1598
|
+
// Update ARIA
|
|
1599
|
+
item.setAttribute('aria-selected', 'false');
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
preparePanel() {
|
|
1604
|
+
this.logger.trace('preparePanel');
|
|
1605
|
+
if (!this.select) {
|
|
1606
|
+
throw new Error('Select element not found');
|
|
1607
|
+
}
|
|
1608
|
+
// Vider le panel (sauf les templates)
|
|
1609
|
+
this.itemsPlace?.querySelectorAll('button').forEach((child) => child.remove());
|
|
1610
|
+
const options = Array.from(this.select.options);
|
|
1611
|
+
options.forEach((option) => {
|
|
1612
|
+
// @ts-ignore
|
|
1613
|
+
const item = this.optionTemplate.content.cloneNode(true);
|
|
1614
|
+
const button = item.querySelector('button');
|
|
1615
|
+
// ARIA attributes
|
|
1616
|
+
button.role = 'option';
|
|
1617
|
+
button.id = `bleet-option-${option.value}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1618
|
+
// Content
|
|
1619
|
+
const itemText = item.querySelector('[data-select=item-text]');
|
|
1620
|
+
const itemValue = item.querySelector('[data-value]');
|
|
1621
|
+
itemValue.dataset.value = option.value;
|
|
1622
|
+
itemText.innerHTML = option.innerHTML;
|
|
1623
|
+
this.itemsPlace?.append(item);
|
|
1624
|
+
});
|
|
1625
|
+
// Appliquer les classes active/inactive
|
|
1626
|
+
this.swapItemClasses();
|
|
1627
|
+
}
|
|
1628
|
+
});
|
|
1629
|
+
return _classThis;
|
|
1630
|
+
})();
|
|
1631
|
+
|
|
1632
|
+
// @ts-ignore
|
|
1633
|
+
let BleetDropdownCustomAttribute = (() => {
|
|
1634
|
+
let _classDecorators = [customAttribute('bleet-dropdown')];
|
|
1635
|
+
let _classDescriptor;
|
|
1636
|
+
let _classExtraInitializers = [];
|
|
1637
|
+
let _classThis;
|
|
1638
|
+
(class {
|
|
1639
|
+
static { _classThis = this; }
|
|
1640
|
+
static {
|
|
1641
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1642
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1643
|
+
_classThis = _classDescriptor.value;
|
|
1644
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1645
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1646
|
+
}
|
|
1647
|
+
logger;
|
|
1648
|
+
element;
|
|
1649
|
+
trapFocusService;
|
|
1650
|
+
select;
|
|
1651
|
+
button;
|
|
1652
|
+
buttonText;
|
|
1653
|
+
optionTemplate;
|
|
1654
|
+
tagTemplate;
|
|
1655
|
+
tagsContainer;
|
|
1656
|
+
placeholder;
|
|
1657
|
+
itemsPlace;
|
|
1658
|
+
itemsContainer;
|
|
1659
|
+
searchInput;
|
|
1660
|
+
emptyMessage;
|
|
1661
|
+
isMultiple = false;
|
|
1662
|
+
withTags = false;
|
|
1663
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-dropdown'), element = resolve(INode), trapFocusService = resolve(ITrapFocusService)) {
|
|
1664
|
+
this.logger = logger;
|
|
1665
|
+
this.element = element;
|
|
1666
|
+
this.trapFocusService = trapFocusService;
|
|
1667
|
+
this.logger.trace('constructor');
|
|
1668
|
+
}
|
|
1669
|
+
attaching() {
|
|
1670
|
+
this.logger.trace('attaching');
|
|
1671
|
+
this.select = this.element.querySelector('select');
|
|
1672
|
+
this.button = this.element.querySelector('button');
|
|
1673
|
+
this.buttonText = this.button.querySelector('[data-dropdown=value]');
|
|
1674
|
+
this.tagsContainer = this.button.querySelector('[data-dropdown=tags]');
|
|
1675
|
+
this.placeholder = this.button.querySelector('[data-dropdown=placeholder]');
|
|
1676
|
+
this.optionTemplate = this.element.querySelector('[data-dropdown=item-template]');
|
|
1677
|
+
this.tagTemplate = this.element.querySelector('[data-dropdown=tag-template]');
|
|
1678
|
+
this.itemsPlace = this.element.querySelector('[data-dropdown=items]');
|
|
1679
|
+
this.itemsContainer = this.element.querySelector('[data-dropdown=items-container]');
|
|
1680
|
+
this.searchInput = this.element.querySelector('[data-dropdown=search]');
|
|
1681
|
+
this.emptyMessage = this.element.querySelector('[data-dropdown=empty]');
|
|
1682
|
+
this.isMultiple = this.select?.multiple || false;
|
|
1683
|
+
this.withTags = this.tagTemplate !== null;
|
|
1684
|
+
}
|
|
1685
|
+
attached() {
|
|
1686
|
+
this.logger.trace('attached');
|
|
1687
|
+
if (!this.itemsPlace) {
|
|
1688
|
+
throw new Error('Items place element not found');
|
|
1689
|
+
}
|
|
1690
|
+
if (!this.itemsPlace.id) {
|
|
1691
|
+
this.itemsPlace.id = `data-dropdown-items-${Math.random().toString(36).substring(2, 15)}`;
|
|
1692
|
+
}
|
|
1693
|
+
if (!this.select?.options) {
|
|
1694
|
+
throw new Error('Select options not found');
|
|
1695
|
+
}
|
|
1696
|
+
if (!this.optionTemplate) {
|
|
1697
|
+
throw new Error('Option template not found');
|
|
1698
|
+
}
|
|
1699
|
+
if (!this.button) {
|
|
1700
|
+
throw new Error('Button element not found');
|
|
1701
|
+
}
|
|
1702
|
+
if (!this.buttonText && !this.tagsContainer) {
|
|
1703
|
+
throw new Error('Button text or tags container element not found');
|
|
1704
|
+
}
|
|
1705
|
+
this.preparePanel();
|
|
1706
|
+
// ARIA setup
|
|
1707
|
+
this.button.ariaHasPopup = 'listbox';
|
|
1708
|
+
this.button.setAttribute('aria-controls', this.itemsPlace.id);
|
|
1709
|
+
this.itemsPlace.role = 'listbox';
|
|
1710
|
+
// Event listeners
|
|
1711
|
+
this.button?.addEventListener('click', this.onClickToggleMenu);
|
|
1712
|
+
this.itemsPlace?.addEventListener('click', this.onClickToggleItem);
|
|
1713
|
+
this.searchInput?.addEventListener('input', this.onSearchInput);
|
|
1714
|
+
// Tag remove event listener (delegation)
|
|
1715
|
+
if (this.withTags) {
|
|
1716
|
+
this.tagsContainer?.addEventListener('click', this.onClickRemoveTag);
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
detached() {
|
|
1720
|
+
this.logger.trace('detached');
|
|
1721
|
+
this.button?.removeEventListener('click', this.onClickToggleMenu);
|
|
1722
|
+
this.itemsPlace?.removeEventListener('click', this.onClickToggleItem);
|
|
1723
|
+
this.searchInput?.removeEventListener('input', this.onSearchInput);
|
|
1724
|
+
if (this.withTags) {
|
|
1725
|
+
this.tagsContainer?.removeEventListener('click', this.onClickRemoveTag);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
onClickToggleMenu = (event) => {
|
|
1729
|
+
this.logger.trace('onClick', event);
|
|
1730
|
+
// Ne pas ouvrir si on clique sur un bouton de suppression de tag
|
|
1731
|
+
if (event.target.closest('[data-dropdown=tag-remove]')) {
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
event.preventDefault();
|
|
1735
|
+
return this.toggleMenu();
|
|
1736
|
+
};
|
|
1737
|
+
onClickRemoveTag = (event) => {
|
|
1738
|
+
const removeButton = event.target.closest('[data-dropdown=tag-remove]');
|
|
1739
|
+
if (!removeButton)
|
|
1740
|
+
return;
|
|
1741
|
+
event.preventDefault();
|
|
1742
|
+
event.stopPropagation();
|
|
1743
|
+
const tagElement = removeButton.closest('[data-tag-value]');
|
|
1744
|
+
if (!tagElement)
|
|
1745
|
+
return;
|
|
1746
|
+
const value = tagElement.dataset.tagValue;
|
|
1747
|
+
// Désélectionner l'option
|
|
1748
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1749
|
+
if (option.value == value) {
|
|
1750
|
+
option.selected = false;
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
// Dispatch change event sur le select natif pour active-form
|
|
1754
|
+
this.select?.dispatchEvent(new Event('change', { bubbles: true }));
|
|
1755
|
+
this.swapItemClasses();
|
|
1756
|
+
this.updateDisplay();
|
|
1757
|
+
};
|
|
1758
|
+
onStopTrapFocus = () => {
|
|
1759
|
+
this.logger.trace('onStopTrapFocus');
|
|
1760
|
+
this.itemsPlace?.classList.add('hidden');
|
|
1761
|
+
// Reset search on close
|
|
1762
|
+
if (this.searchInput) {
|
|
1763
|
+
this.searchInput.value = '';
|
|
1764
|
+
this.filterItems('');
|
|
1765
|
+
}
|
|
1766
|
+
return Promise.resolve();
|
|
1767
|
+
};
|
|
1768
|
+
toggleMenu = () => {
|
|
1769
|
+
const isClosed = this.itemsPlace?.classList.contains('hidden');
|
|
1770
|
+
return new Promise((resolve) => {
|
|
1771
|
+
if (isClosed) {
|
|
1772
|
+
// Opening menu
|
|
1773
|
+
this.button.ariaExpanded = 'true';
|
|
1774
|
+
// Find selected option to focus initially, or search input if searchable
|
|
1775
|
+
const initialFocus = this.searchInput || this.itemsPlace?.querySelector('[aria-selected="true"]');
|
|
1776
|
+
return this.trapFocusService.start(this.button, this.itemsPlace, this.element, undefined, this.onStopTrapFocus, initialFocus)
|
|
1777
|
+
.then(() => {
|
|
1778
|
+
this.logger.trace('toggleMenu opened');
|
|
1779
|
+
this.itemsPlace?.classList.remove('hidden');
|
|
1780
|
+
resolve(void 0);
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
else {
|
|
1784
|
+
// Closing menu
|
|
1785
|
+
this.button.ariaExpanded = 'false';
|
|
1786
|
+
return this.trapFocusService.stop()
|
|
1787
|
+
.then(() => {
|
|
1788
|
+
this.logger.trace('toggleMenu closed');
|
|
1789
|
+
this.itemsPlace?.classList.add('hidden');
|
|
1790
|
+
resolve(void 0);
|
|
1791
|
+
});
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
};
|
|
1795
|
+
onClickToggleItem = (event) => {
|
|
1796
|
+
this.logger.trace('onClickItem', event);
|
|
1797
|
+
event.preventDefault();
|
|
1798
|
+
const element = event.target.closest('[data-value]');
|
|
1799
|
+
if (!element)
|
|
1800
|
+
return;
|
|
1801
|
+
const clickedValue = element.dataset.value;
|
|
1802
|
+
if (this.isMultiple) {
|
|
1803
|
+
// Toggle la sélection de l'option cliquée
|
|
1804
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1805
|
+
if (option.value == clickedValue) {
|
|
1806
|
+
option.selected = !option.selected;
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
// Dispatch change event sur le select natif pour active-form
|
|
1810
|
+
this.select?.dispatchEvent(new Event('change', { bubbles: true }));
|
|
1811
|
+
// Ne pas fermer le menu en mode multiple
|
|
1812
|
+
this.swapItemClasses();
|
|
1813
|
+
this.updateDisplay();
|
|
1814
|
+
}
|
|
1815
|
+
else {
|
|
1816
|
+
// Mode simple : une seule sélection
|
|
1817
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1818
|
+
option.selected = option.value == clickedValue;
|
|
1819
|
+
});
|
|
1820
|
+
// Dispatch change event sur le select natif pour active-form
|
|
1821
|
+
this.select?.dispatchEvent(new Event('change', { bubbles: true }));
|
|
1822
|
+
this.synchSelect();
|
|
1823
|
+
}
|
|
1824
|
+
};
|
|
1825
|
+
onSearchInput = (event) => {
|
|
1826
|
+
const query = event.target.value;
|
|
1827
|
+
this.filterItems(query);
|
|
1828
|
+
};
|
|
1829
|
+
filterItems(query) {
|
|
1830
|
+
const normalizedQuery = query.toLowerCase().trim();
|
|
1831
|
+
let visibleCount = 0;
|
|
1832
|
+
this.itemsContainer?.querySelectorAll('[data-value]').forEach((item) => {
|
|
1833
|
+
const text = item.querySelector('[data-dropdown=item-text]')?.textContent?.toLowerCase() || '';
|
|
1834
|
+
const isVisible = normalizedQuery === '' || text.includes(normalizedQuery);
|
|
1835
|
+
if (isVisible) {
|
|
1836
|
+
item.classList.remove('hidden');
|
|
1837
|
+
visibleCount++;
|
|
1838
|
+
}
|
|
1839
|
+
else {
|
|
1840
|
+
item.classList.add('hidden');
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
// Show/hide empty message
|
|
1844
|
+
if (this.emptyMessage) {
|
|
1845
|
+
if (visibleCount === 0 && normalizedQuery !== '') {
|
|
1846
|
+
this.emptyMessage.classList.remove('hidden');
|
|
1847
|
+
}
|
|
1848
|
+
else {
|
|
1849
|
+
this.emptyMessage.classList.add('hidden');
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
synchSelect() {
|
|
1854
|
+
this.swapItemClasses();
|
|
1855
|
+
// Close menu
|
|
1856
|
+
return this.toggleMenu();
|
|
1857
|
+
}
|
|
1858
|
+
updateDisplay() {
|
|
1859
|
+
if (this.withTags) {
|
|
1860
|
+
this.updateTags();
|
|
1861
|
+
}
|
|
1862
|
+
else {
|
|
1863
|
+
this.updateButtonText();
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
updateButtonText() {
|
|
1867
|
+
const selectedOptions = Array.from(this.select.options).filter(opt => opt.selected);
|
|
1868
|
+
if (selectedOptions.length === 0) {
|
|
1869
|
+
// Afficher le placeholder s'il existe
|
|
1870
|
+
const placeholder = Array.from(this.select.options).find(opt => opt.value === '');
|
|
1871
|
+
this.buttonText.innerHTML = placeholder?.innerHTML || '';
|
|
1872
|
+
}
|
|
1873
|
+
else if (selectedOptions.length === 1) {
|
|
1874
|
+
this.buttonText.innerHTML = selectedOptions[0].innerHTML;
|
|
1875
|
+
}
|
|
1876
|
+
else {
|
|
1877
|
+
this.buttonText.textContent = `${selectedOptions.length} sélectionnés`;
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
updateTags() {
|
|
1881
|
+
if (!this.tagsContainer || !this.tagTemplate)
|
|
1882
|
+
return;
|
|
1883
|
+
const selectedOptions = Array.from(this.select.options).filter(opt => opt.selected && opt.value !== '');
|
|
1884
|
+
// Supprimer les tags existants (sauf le placeholder)
|
|
1885
|
+
this.tagsContainer.querySelectorAll('[data-tag-value]').forEach(tag => tag.remove());
|
|
1886
|
+
// Afficher/masquer le placeholder
|
|
1887
|
+
if (this.placeholder) {
|
|
1888
|
+
if (selectedOptions.length === 0) {
|
|
1889
|
+
this.placeholder.classList.remove('hidden');
|
|
1890
|
+
}
|
|
1891
|
+
else {
|
|
1892
|
+
this.placeholder.classList.add('hidden');
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
// Créer les tags
|
|
1896
|
+
selectedOptions.forEach((option) => {
|
|
1897
|
+
const tagFragment = this.tagTemplate.content.cloneNode(true);
|
|
1898
|
+
const tagElement = tagFragment.querySelector('[data-tag-value]');
|
|
1899
|
+
const tagText = tagFragment.querySelector('[data-dropdown=tag-text]');
|
|
1900
|
+
tagElement.dataset.tagValue = option.value;
|
|
1901
|
+
tagText.textContent = option.textContent;
|
|
1902
|
+
this.tagsContainer?.appendChild(tagFragment);
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
swapItemClasses() {
|
|
1906
|
+
Array.from(this.select.options).forEach((option) => {
|
|
1907
|
+
const item = this.itemsContainer?.querySelector(`[data-value="${option.value}"]`);
|
|
1908
|
+
if (!item)
|
|
1909
|
+
return;
|
|
1910
|
+
const checkmark = item.querySelector('[data-dropdown=item-check]');
|
|
1911
|
+
// Récupérer les classes depuis les data-attributes de l'élément
|
|
1912
|
+
const itemInactiveClasses = item.dataset.classInactive?.split(' ') || [];
|
|
1913
|
+
const itemActiveClasses = item.dataset.classActive?.split(' ') || [];
|
|
1914
|
+
const checkInactiveClasses = checkmark?.dataset.classInactive?.split(' ') || [];
|
|
1915
|
+
const checkActiveClasses = checkmark?.dataset.classActive?.split(' ') || [];
|
|
1916
|
+
if (option.selected) {
|
|
1917
|
+
// Swap vers active
|
|
1918
|
+
item.classList.remove(...itemInactiveClasses);
|
|
1919
|
+
item.classList.add(...itemActiveClasses);
|
|
1920
|
+
checkmark?.classList.remove(...checkInactiveClasses);
|
|
1921
|
+
checkmark?.classList.add(...checkActiveClasses);
|
|
1922
|
+
// Update ARIA
|
|
1923
|
+
item.setAttribute('aria-selected', 'true');
|
|
1924
|
+
this.button?.setAttribute('aria-activedescendant', item.id);
|
|
1925
|
+
}
|
|
1926
|
+
else {
|
|
1927
|
+
// Swap vers inactive
|
|
1928
|
+
item.classList.remove(...itemActiveClasses);
|
|
1929
|
+
item.classList.add(...itemInactiveClasses);
|
|
1930
|
+
checkmark?.classList.remove(...checkActiveClasses);
|
|
1931
|
+
checkmark?.classList.add(...checkInactiveClasses);
|
|
1932
|
+
// Update ARIA
|
|
1933
|
+
item.setAttribute('aria-selected', 'false');
|
|
1934
|
+
}
|
|
1935
|
+
});
|
|
1936
|
+
// Update display (text or tags)
|
|
1937
|
+
this.updateDisplay();
|
|
1938
|
+
}
|
|
1939
|
+
preparePanel() {
|
|
1940
|
+
this.logger.trace('preparePanel');
|
|
1941
|
+
if (!this.select) {
|
|
1942
|
+
throw new Error('Select element not found');
|
|
1943
|
+
}
|
|
1944
|
+
// Vider le container
|
|
1945
|
+
if (this.itemsContainer) {
|
|
1946
|
+
this.itemsContainer.innerHTML = '';
|
|
1947
|
+
}
|
|
1948
|
+
const options = Array.from(this.select.options);
|
|
1949
|
+
options.forEach((option) => {
|
|
1950
|
+
// @ts-ignore
|
|
1951
|
+
const item = this.optionTemplate.content.cloneNode(true);
|
|
1952
|
+
const button = item.querySelector('button');
|
|
1953
|
+
// ARIA attributes
|
|
1954
|
+
button.role = 'option';
|
|
1955
|
+
button.id = `bleet-option-${option.value}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1956
|
+
// Content
|
|
1957
|
+
const itemText = item.querySelector('[data-dropdown=item-text]');
|
|
1958
|
+
const itemValue = item.querySelector('[data-value]');
|
|
1959
|
+
itemValue.dataset.value = option.value;
|
|
1960
|
+
itemText.innerHTML = option.innerHTML;
|
|
1961
|
+
this.itemsContainer?.append(item);
|
|
1962
|
+
});
|
|
1963
|
+
// Appliquer les classes active/inactive
|
|
1964
|
+
this.swapItemClasses();
|
|
1965
|
+
}
|
|
1966
|
+
});
|
|
1967
|
+
return _classThis;
|
|
1968
|
+
})();
|
|
1969
|
+
|
|
1970
|
+
let BleetPasswordCustomAttribute = (() => {
|
|
1971
|
+
let _classDecorators = [customAttribute('bleet-password')];
|
|
1972
|
+
let _classDescriptor;
|
|
1973
|
+
let _classExtraInitializers = [];
|
|
1974
|
+
let _classThis;
|
|
1975
|
+
(class {
|
|
1976
|
+
static { _classThis = this; }
|
|
1977
|
+
static {
|
|
1978
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1979
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1980
|
+
_classThis = _classDescriptor.value;
|
|
1981
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1982
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1983
|
+
}
|
|
1984
|
+
logger;
|
|
1985
|
+
element;
|
|
1986
|
+
button;
|
|
1987
|
+
iconHidden;
|
|
1988
|
+
iconVisible;
|
|
1989
|
+
input;
|
|
1990
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-password'), element = resolve(INode)) {
|
|
1991
|
+
this.logger = logger;
|
|
1992
|
+
this.element = element;
|
|
1993
|
+
}
|
|
1994
|
+
attaching() {
|
|
1995
|
+
this.button = this.element.querySelector('[data-password=toggle]') ?? undefined;
|
|
1996
|
+
this.iconHidden = this.button?.querySelector('[data-password=icon-hidden]') ?? undefined;
|
|
1997
|
+
this.iconVisible = this.button?.querySelector('[data-password=icon-visible]') ?? undefined;
|
|
1998
|
+
this.input = this.element.querySelector('input') ?? undefined;
|
|
1999
|
+
}
|
|
2000
|
+
attached() {
|
|
2001
|
+
this.button?.addEventListener('click', this.onToggle);
|
|
2002
|
+
}
|
|
2003
|
+
detaching() {
|
|
2004
|
+
this.button?.removeEventListener('click', this.onToggle);
|
|
2005
|
+
}
|
|
2006
|
+
onToggle = (event) => {
|
|
2007
|
+
event.preventDefault();
|
|
2008
|
+
const isPassword = this.input?.type === 'password';
|
|
2009
|
+
if (this.input) {
|
|
2010
|
+
this.input.type = isPassword ? 'text' : 'password';
|
|
2011
|
+
}
|
|
2012
|
+
this.iconHidden?.classList.toggle('hidden', isPassword);
|
|
2013
|
+
this.iconVisible?.classList.toggle('hidden', !isPassword);
|
|
2014
|
+
};
|
|
2015
|
+
});
|
|
2016
|
+
return _classThis;
|
|
2017
|
+
})();
|
|
2018
|
+
|
|
2019
|
+
let BleetTabsCustomAttribute = (() => {
|
|
2020
|
+
let _classDecorators = [customAttribute('bleet-tabs')];
|
|
2021
|
+
let _classDescriptor;
|
|
2022
|
+
let _classExtraInitializers = [];
|
|
2023
|
+
let _classThis;
|
|
2024
|
+
(class {
|
|
2025
|
+
static { _classThis = this; }
|
|
2026
|
+
static {
|
|
2027
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2028
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2029
|
+
_classThis = _classDescriptor.value;
|
|
2030
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2031
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2032
|
+
}
|
|
2033
|
+
logger;
|
|
2034
|
+
element;
|
|
2035
|
+
p;
|
|
2036
|
+
activeClasses = '';
|
|
2037
|
+
inactiveClasses = '';
|
|
2038
|
+
select;
|
|
2039
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-tabs'), element = resolve(INode), p = resolve(IPlatform)) {
|
|
2040
|
+
this.logger = logger;
|
|
2041
|
+
this.element = element;
|
|
2042
|
+
this.p = p;
|
|
2043
|
+
this.logger.trace('constructor');
|
|
2044
|
+
}
|
|
2045
|
+
attaching() {
|
|
2046
|
+
this.logger.trace('attaching');
|
|
2047
|
+
const activeButton = this.element.querySelector('[data-tabs^="tab-"][aria-selected="true"]');
|
|
2048
|
+
const inactiveButton = this.element.querySelector('[data-tabs^="tab-"][aria-selected="false"]');
|
|
2049
|
+
this.activeClasses = activeButton?.className || '';
|
|
2050
|
+
this.inactiveClasses = inactiveButton?.className || '';
|
|
2051
|
+
this.select = this.element.querySelector('select');
|
|
2052
|
+
}
|
|
2053
|
+
attached() {
|
|
2054
|
+
this.logger.trace('attached');
|
|
2055
|
+
this.element.querySelectorAll('[data-tabs^="tab-"]').forEach((button) => {
|
|
2056
|
+
button.addEventListener('click', this.onClickTab);
|
|
2057
|
+
});
|
|
2058
|
+
// Écouter le select mobile
|
|
2059
|
+
if (this.select) {
|
|
2060
|
+
this.select.addEventListener('change', this.onChangeSelect);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
detached() {
|
|
2064
|
+
this.logger.trace('detached');
|
|
2065
|
+
this.element.querySelectorAll('[data-tabs^="tab-"]').forEach((button) => {
|
|
2066
|
+
button.removeEventListener('click', this.onClickTab);
|
|
2067
|
+
});
|
|
2068
|
+
if (this.select) {
|
|
2069
|
+
this.select.removeEventListener('change', this.onChangeSelect);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
onClickTab = (event) => {
|
|
2073
|
+
this.logger.trace('onClickTab', event);
|
|
2074
|
+
event.preventDefault();
|
|
2075
|
+
const tabIndex = event.currentTarget.getAttribute('data-tabs')?.replace('tab-', '') || '0';
|
|
2076
|
+
// Mettre à jour les tabs
|
|
2077
|
+
this.element.querySelectorAll('[data-tabs^="tab-"]').forEach((button) => {
|
|
2078
|
+
const buttonTabIndex = button.getAttribute('data-tabs')?.replace('tab-', '') || '0';
|
|
2079
|
+
if (buttonTabIndex === tabIndex) {
|
|
2080
|
+
button.setAttribute('aria-selected', 'true');
|
|
2081
|
+
button.className = this.activeClasses;
|
|
2082
|
+
}
|
|
2083
|
+
else {
|
|
2084
|
+
button.setAttribute('aria-selected', 'false');
|
|
2085
|
+
button.className = this.inactiveClasses;
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
// Mettre à jour les panels
|
|
2089
|
+
this.element.querySelectorAll('[data-tabs^="panel-"]').forEach((panel) => {
|
|
2090
|
+
const panelIndex = panel.getAttribute('data-tabs')?.replace('panel-', '') || '0';
|
|
2091
|
+
if (panelIndex === tabIndex) {
|
|
2092
|
+
panel.classList.remove('hidden');
|
|
2093
|
+
panel.setAttribute('aria-hidden', 'false');
|
|
2094
|
+
}
|
|
2095
|
+
else {
|
|
2096
|
+
panel.classList.add('hidden');
|
|
2097
|
+
panel.setAttribute('aria-hidden', 'true');
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
// Synchroniser le select
|
|
2101
|
+
if (this.select) {
|
|
2102
|
+
this.select.value = tabIndex;
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
onChangeSelect = (event) => {
|
|
2106
|
+
this.logger.trace('onChangeSelect', event);
|
|
2107
|
+
const tabIndex = this.select?.value;
|
|
2108
|
+
const button = this.element.querySelector(`[data-tabs="tab-${tabIndex}"]`);
|
|
2109
|
+
if (button) {
|
|
2110
|
+
button.click();
|
|
2111
|
+
}
|
|
2112
|
+
};
|
|
2113
|
+
});
|
|
2114
|
+
return _classThis;
|
|
2115
|
+
})();
|
|
2116
|
+
|
|
2117
|
+
let BleetProfileCustomAttribute = (() => {
|
|
2118
|
+
let _classDecorators = [customAttribute({ name: 'bleet-profile', defaultProperty: 'id' })];
|
|
2119
|
+
let _classDescriptor;
|
|
2120
|
+
let _classExtraInitializers = [];
|
|
2121
|
+
let _classThis;
|
|
2122
|
+
let _id_decorators;
|
|
2123
|
+
let _id_initializers = [];
|
|
2124
|
+
let _id_extraInitializers = [];
|
|
2125
|
+
(class {
|
|
2126
|
+
static { _classThis = this; }
|
|
2127
|
+
static {
|
|
2128
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2129
|
+
_id_decorators = [bindable];
|
|
2130
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
2131
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2132
|
+
_classThis = _classDescriptor.value;
|
|
2133
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2134
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2135
|
+
}
|
|
2136
|
+
logger;
|
|
2137
|
+
ea;
|
|
2138
|
+
element;
|
|
2139
|
+
transitionService;
|
|
2140
|
+
platform;
|
|
2141
|
+
trapFocusService;
|
|
2142
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
2143
|
+
toggleButton = __runInitializers(this, _id_extraInitializers);
|
|
2144
|
+
panel;
|
|
2145
|
+
isOpen = false;
|
|
2146
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-profile'), ea = resolve(IEventAggregator), element = resolve(INode), transitionService = resolve(ITransitionService), platform = resolve(IPlatform), trapFocusService = resolve(ITrapFocusService)) {
|
|
2147
|
+
this.logger = logger;
|
|
2148
|
+
this.ea = ea;
|
|
2149
|
+
this.element = element;
|
|
2150
|
+
this.transitionService = transitionService;
|
|
2151
|
+
this.platform = platform;
|
|
2152
|
+
this.trapFocusService = trapFocusService;
|
|
2153
|
+
this.logger.trace('constructor');
|
|
2154
|
+
}
|
|
2155
|
+
attaching() {
|
|
2156
|
+
this.logger.trace('attaching');
|
|
2157
|
+
this.toggleButton = this.element.querySelector('[data-profile=toggle]');
|
|
2158
|
+
this.panel = this.element.querySelector('[data-profile=panel]');
|
|
2159
|
+
}
|
|
2160
|
+
attached() {
|
|
2161
|
+
this.logger.trace('attached');
|
|
2162
|
+
this.toggleButton?.addEventListener('click', this.onClickToggle);
|
|
2163
|
+
}
|
|
2164
|
+
detached() {
|
|
2165
|
+
this.logger.trace('detached');
|
|
2166
|
+
this.toggleButton?.removeEventListener('click', this.onClickToggle);
|
|
2167
|
+
if (this.isOpen) {
|
|
2168
|
+
this.trapFocusService.stop();
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
onClickToggle = (event) => {
|
|
2172
|
+
this.logger.trace('onClickToggle', event);
|
|
2173
|
+
event.preventDefault();
|
|
2174
|
+
if (this.isOpen) {
|
|
2175
|
+
this.close();
|
|
2176
|
+
}
|
|
2177
|
+
else {
|
|
2178
|
+
this.open();
|
|
2179
|
+
}
|
|
2180
|
+
};
|
|
2181
|
+
onStopTrapFocus = () => {
|
|
2182
|
+
this.logger.trace('onStopTrapFocus');
|
|
2183
|
+
this.isOpen = false;
|
|
2184
|
+
this.toggleButton?.setAttribute('aria-expanded', 'false');
|
|
2185
|
+
this.transitionService.run(this.panel, (element) => {
|
|
2186
|
+
this.ea.publish(Channels.Profile, { action: ProfileAction.Close, id: this.id });
|
|
2187
|
+
this.ea.publish(Channels.ProfileStatus, { status: ProfileStatus.Closing, id: this.id });
|
|
2188
|
+
this.platform.requestAnimationFrame(() => {
|
|
2189
|
+
element.classList.remove('opacity-100', 'scale-100');
|
|
2190
|
+
element.classList.add('opacity-0', 'scale-95', 'pointer-events-none');
|
|
2191
|
+
});
|
|
2192
|
+
}, (element) => {
|
|
2193
|
+
element.classList.add('hidden');
|
|
2194
|
+
this.ea.publish(Channels.ProfileStatus, { status: ProfileStatus.Closed, id: this.id });
|
|
2195
|
+
});
|
|
2196
|
+
return Promise.resolve();
|
|
2197
|
+
};
|
|
2198
|
+
open() {
|
|
2199
|
+
this.logger.trace('open');
|
|
2200
|
+
this.isOpen = true;
|
|
2201
|
+
this.toggleButton?.setAttribute('aria-expanded', 'true');
|
|
2202
|
+
// Find first focusable item in panel
|
|
2203
|
+
const firstItem = this.panel?.querySelector('a, button');
|
|
2204
|
+
this.trapFocusService.start(this.toggleButton, this.panel, this.element, undefined, this.onStopTrapFocus, firstItem).then(() => {
|
|
2205
|
+
this.transitionService.run(this.panel, (element) => {
|
|
2206
|
+
this.ea.publish(Channels.Profile, { action: ProfileAction.Open, id: this.id });
|
|
2207
|
+
this.ea.publish(Channels.ProfileStatus, { status: ProfileStatus.Opening, id: this.id });
|
|
2208
|
+
element.classList.remove('hidden');
|
|
2209
|
+
this.platform.requestAnimationFrame(() => {
|
|
2210
|
+
element.classList.add('opacity-100', 'scale-100');
|
|
2211
|
+
element.classList.remove('opacity-0', 'scale-95', 'pointer-events-none');
|
|
2212
|
+
});
|
|
2213
|
+
}, () => {
|
|
2214
|
+
this.ea.publish(Channels.ProfileStatus, { status: ProfileStatus.Opened, id: this.id });
|
|
2215
|
+
});
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
close() {
|
|
2219
|
+
this.logger.trace('close');
|
|
2220
|
+
this.trapFocusService.stop();
|
|
2221
|
+
}
|
|
2222
|
+
});
|
|
2223
|
+
return _classThis;
|
|
2224
|
+
})();
|
|
2225
|
+
|
|
2226
|
+
let BleetToasterTriggerCustomAttribute = (() => {
|
|
2227
|
+
let _classDecorators = [customAttribute({ name: 'bleet-toaster-trigger', defaultProperty: 'id' })];
|
|
2228
|
+
let _classDescriptor;
|
|
2229
|
+
let _classExtraInitializers = [];
|
|
2230
|
+
let _classThis;
|
|
2231
|
+
let _id_decorators;
|
|
2232
|
+
let _id_initializers = [];
|
|
2233
|
+
let _id_extraInitializers = [];
|
|
2234
|
+
let _color_decorators;
|
|
2235
|
+
let _color_initializers = [];
|
|
2236
|
+
let _color_extraInitializers = [];
|
|
2237
|
+
let _icon_decorators;
|
|
2238
|
+
let _icon_initializers = [];
|
|
2239
|
+
let _icon_extraInitializers = [];
|
|
2240
|
+
let _title_decorators;
|
|
2241
|
+
let _title_initializers = [];
|
|
2242
|
+
let _title_extraInitializers = [];
|
|
2243
|
+
let _content_decorators;
|
|
2244
|
+
let _content_initializers = [];
|
|
2245
|
+
let _content_extraInitializers = [];
|
|
2246
|
+
let _duration_decorators;
|
|
2247
|
+
let _duration_initializers = [];
|
|
2248
|
+
let _duration_extraInitializers = [];
|
|
2249
|
+
(class {
|
|
2250
|
+
static { _classThis = this; }
|
|
2251
|
+
static {
|
|
2252
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2253
|
+
_id_decorators = [bindable];
|
|
2254
|
+
_color_decorators = [bindable()];
|
|
2255
|
+
_icon_decorators = [bindable()];
|
|
2256
|
+
_title_decorators = [bindable()];
|
|
2257
|
+
_content_decorators = [bindable()];
|
|
2258
|
+
_duration_decorators = [bindable()];
|
|
2259
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
2260
|
+
__esDecorate(null, null, _color_decorators, { kind: "field", name: "color", static: false, private: false, access: { has: obj => "color" in obj, get: obj => obj.color, set: (obj, value) => { obj.color = value; } }, metadata: _metadata }, _color_initializers, _color_extraInitializers);
|
|
2261
|
+
__esDecorate(null, null, _icon_decorators, { kind: "field", name: "icon", static: false, private: false, access: { has: obj => "icon" in obj, get: obj => obj.icon, set: (obj, value) => { obj.icon = value; } }, metadata: _metadata }, _icon_initializers, _icon_extraInitializers);
|
|
2262
|
+
__esDecorate(null, null, _title_decorators, { kind: "field", name: "title", static: false, private: false, access: { has: obj => "title" in obj, get: obj => obj.title, set: (obj, value) => { obj.title = value; } }, metadata: _metadata }, _title_initializers, _title_extraInitializers);
|
|
2263
|
+
__esDecorate(null, null, _content_decorators, { kind: "field", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content, set: (obj, value) => { obj.content = value; } }, metadata: _metadata }, _content_initializers, _content_extraInitializers);
|
|
2264
|
+
__esDecorate(null, null, _duration_decorators, { kind: "field", name: "duration", static: false, private: false, access: { has: obj => "duration" in obj, get: obj => obj.duration, set: (obj, value) => { obj.duration = value; } }, metadata: _metadata }, _duration_initializers, _duration_extraInitializers);
|
|
2265
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2266
|
+
_classThis = _classDescriptor.value;
|
|
2267
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2268
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2269
|
+
}
|
|
2270
|
+
logger;
|
|
2271
|
+
element;
|
|
2272
|
+
ea;
|
|
2273
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
2274
|
+
color = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _color_initializers, UiColor.Info));
|
|
2275
|
+
icon = (__runInitializers(this, _color_extraInitializers), __runInitializers(this, _icon_initializers, UiToastIcon.Info));
|
|
2276
|
+
title = (__runInitializers(this, _icon_extraInitializers), __runInitializers(this, _title_initializers, ''));
|
|
2277
|
+
content = (__runInitializers(this, _title_extraInitializers), __runInitializers(this, _content_initializers, ''));
|
|
2278
|
+
duration = (__runInitializers(this, _content_extraInitializers), __runInitializers(this, _duration_initializers, 0)); // Duration in milliseconds
|
|
2279
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-toaster-trigger'), element = resolve(INode), ea = resolve(IEventAggregator)) {
|
|
2280
|
+
this.logger = logger;
|
|
2281
|
+
this.element = element;
|
|
2282
|
+
this.ea = ea;
|
|
2283
|
+
this.logger.trace('constructor');
|
|
2284
|
+
}
|
|
2285
|
+
attaching() {
|
|
2286
|
+
this.logger.trace('attaching');
|
|
2287
|
+
}
|
|
2288
|
+
attached() {
|
|
2289
|
+
this.logger.trace('attached');
|
|
2290
|
+
this.element.addEventListener('click', this.onClick);
|
|
2291
|
+
}
|
|
2292
|
+
detached() {
|
|
2293
|
+
this.logger.trace('detached');
|
|
2294
|
+
this.element.removeEventListener('click', this.onClick);
|
|
2295
|
+
}
|
|
2296
|
+
onClick = (__runInitializers(this, _duration_extraInitializers), (event) => {
|
|
2297
|
+
this.logger.trace('onClick', event);
|
|
2298
|
+
event.preventDefault();
|
|
2299
|
+
this.ea.publish(Channels.Toaster, {
|
|
2300
|
+
action: ToasterAction.Add, toast: {
|
|
2301
|
+
id: this.id,
|
|
2302
|
+
duration: this.duration,
|
|
2303
|
+
color: this.color,
|
|
2304
|
+
icon: this.icon,
|
|
2305
|
+
title: this.title,
|
|
2306
|
+
content: this.content
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
});
|
|
2310
|
+
});
|
|
2311
|
+
return _classThis;
|
|
2312
|
+
})();
|
|
2313
|
+
|
|
2314
|
+
let BleetAlertCustomAttribute = (() => {
|
|
2315
|
+
let _classDecorators = [customAttribute('bleet-alert')];
|
|
2316
|
+
let _classDescriptor;
|
|
2317
|
+
let _classExtraInitializers = [];
|
|
2318
|
+
let _classThis;
|
|
2319
|
+
(class {
|
|
2320
|
+
static { _classThis = this; }
|
|
2321
|
+
static {
|
|
2322
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2323
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2324
|
+
_classThis = _classDescriptor.value;
|
|
2325
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2326
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2327
|
+
}
|
|
2328
|
+
logger;
|
|
2329
|
+
element;
|
|
2330
|
+
platform;
|
|
2331
|
+
transitionService;
|
|
2332
|
+
closeButton;
|
|
2333
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-alert'), element = resolve(INode), platform = resolve(IPlatform), transitionService = resolve(ITransitionService)) {
|
|
2334
|
+
this.logger = logger;
|
|
2335
|
+
this.element = element;
|
|
2336
|
+
this.platform = platform;
|
|
2337
|
+
this.transitionService = transitionService;
|
|
2338
|
+
this.logger.trace('constructor');
|
|
2339
|
+
}
|
|
2340
|
+
attaching() {
|
|
2341
|
+
this.logger.trace('attaching');
|
|
2342
|
+
this.closeButton = this.element.querySelector('[data-alert=close]');
|
|
2343
|
+
}
|
|
2344
|
+
attached() {
|
|
2345
|
+
this.logger.trace('attached');
|
|
2346
|
+
this.closeButton?.addEventListener('click', this.onClose);
|
|
2347
|
+
}
|
|
2348
|
+
detached() {
|
|
2349
|
+
this.logger.trace('detached');
|
|
2350
|
+
this.closeButton?.removeEventListener('click', this.onClose);
|
|
2351
|
+
}
|
|
2352
|
+
onClose = (event) => {
|
|
2353
|
+
this.logger.trace('onClose', event);
|
|
2354
|
+
event.preventDefault();
|
|
2355
|
+
this.transitionService.run(this.element, (element) => {
|
|
2356
|
+
const currentHeight = element.scrollHeight;
|
|
2357
|
+
element.style.height = currentHeight + 'px';
|
|
2358
|
+
// Force reflow
|
|
2359
|
+
element.offsetHeight;
|
|
2360
|
+
element.style.height = '0px';
|
|
2361
|
+
element.classList.remove('opacity-100');
|
|
2362
|
+
element.classList.add('opacity-0');
|
|
2363
|
+
}, (element) => {
|
|
2364
|
+
element.classList.add('hidden');
|
|
2365
|
+
this.platform.requestAnimationFrame(() => {
|
|
2366
|
+
element.style.height = '';
|
|
2367
|
+
element.remove();
|
|
2368
|
+
});
|
|
2369
|
+
});
|
|
2370
|
+
};
|
|
2371
|
+
});
|
|
2372
|
+
return _classThis;
|
|
2373
|
+
})();
|
|
2374
|
+
|
|
2375
|
+
let BleetDrawerTriggerCustomAttribute = (() => {
|
|
2376
|
+
let _classDecorators = [customAttribute({ name: 'bleet-drawer-trigger', defaultProperty: 'id' })];
|
|
2377
|
+
let _classDescriptor;
|
|
2378
|
+
let _classExtraInitializers = [];
|
|
2379
|
+
let _classThis;
|
|
2380
|
+
let _id_decorators;
|
|
2381
|
+
let _id_initializers = [];
|
|
2382
|
+
let _id_extraInitializers = [];
|
|
2383
|
+
let _url_decorators;
|
|
2384
|
+
let _url_initializers = [];
|
|
2385
|
+
let _url_extraInitializers = [];
|
|
2386
|
+
let _color_decorators;
|
|
2387
|
+
let _color_initializers = [];
|
|
2388
|
+
let _color_extraInitializers = [];
|
|
2389
|
+
(class {
|
|
2390
|
+
static { _classThis = this; }
|
|
2391
|
+
static {
|
|
2392
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2393
|
+
_id_decorators = [bindable];
|
|
2394
|
+
_url_decorators = [bindable()];
|
|
2395
|
+
_color_decorators = [bindable()];
|
|
2396
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
2397
|
+
__esDecorate(null, null, _url_decorators, { kind: "field", name: "url", static: false, private: false, access: { has: obj => "url" in obj, get: obj => obj.url, set: (obj, value) => { obj.url = value; } }, metadata: _metadata }, _url_initializers, _url_extraInitializers);
|
|
2398
|
+
__esDecorate(null, null, _color_decorators, { kind: "field", name: "color", static: false, private: false, access: { has: obj => "color" in obj, get: obj => obj.color, set: (obj, value) => { obj.color = value; } }, metadata: _metadata }, _color_initializers, _color_extraInitializers);
|
|
2399
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2400
|
+
_classThis = _classDescriptor.value;
|
|
2401
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2402
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2403
|
+
}
|
|
2404
|
+
logger;
|
|
2405
|
+
element;
|
|
2406
|
+
ea;
|
|
2407
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
2408
|
+
url = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _url_initializers, ''));
|
|
2409
|
+
color = (__runInitializers(this, _url_extraInitializers), __runInitializers(this, _color_initializers, 'primary'));
|
|
2410
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-drawer-trigger'), element = resolve(INode), ea = resolve(IEventAggregator)) {
|
|
2411
|
+
this.logger = logger;
|
|
2412
|
+
this.element = element;
|
|
2413
|
+
this.ea = ea;
|
|
2414
|
+
this.logger.trace('constructor');
|
|
2415
|
+
}
|
|
2416
|
+
attaching() {
|
|
2417
|
+
this.logger.trace('attaching');
|
|
2418
|
+
}
|
|
2419
|
+
attached() {
|
|
2420
|
+
this.logger.trace('attached');
|
|
2421
|
+
this.element.addEventListener('click', this.onClick);
|
|
2422
|
+
}
|
|
2423
|
+
detached() {
|
|
2424
|
+
this.logger.trace('detached');
|
|
2425
|
+
this.element.removeEventListener('click', this.onClick);
|
|
2426
|
+
}
|
|
2427
|
+
dispose() {
|
|
2428
|
+
this.logger.trace('dispose');
|
|
2429
|
+
}
|
|
2430
|
+
onClick = (__runInitializers(this, _color_extraInitializers), (event) => {
|
|
2431
|
+
this.logger.trace('onClick', event);
|
|
2432
|
+
event.preventDefault();
|
|
2433
|
+
this.ea.publish(Channels.Drawer, {
|
|
2434
|
+
action: DrawerAction.Toggle,
|
|
2435
|
+
id: this.id,
|
|
2436
|
+
url: this.url,
|
|
2437
|
+
color: this.color,
|
|
2438
|
+
});
|
|
2439
|
+
});
|
|
2440
|
+
});
|
|
2441
|
+
return _classThis;
|
|
2442
|
+
})();
|
|
2443
|
+
|
|
2444
|
+
let BleetModalTriggerCustomAttribute = (() => {
|
|
2445
|
+
let _classDecorators = [customAttribute({ name: 'bleet-modal-trigger', defaultProperty: 'id' })];
|
|
2446
|
+
let _classDescriptor;
|
|
2447
|
+
let _classExtraInitializers = [];
|
|
2448
|
+
let _classThis;
|
|
2449
|
+
let _id_decorators;
|
|
2450
|
+
let _id_initializers = [];
|
|
2451
|
+
let _id_extraInitializers = [];
|
|
2452
|
+
let _url_decorators;
|
|
2453
|
+
let _url_initializers = [];
|
|
2454
|
+
let _url_extraInitializers = [];
|
|
2455
|
+
let _color_decorators;
|
|
2456
|
+
let _color_initializers = [];
|
|
2457
|
+
let _color_extraInitializers = [];
|
|
2458
|
+
(class {
|
|
2459
|
+
static { _classThis = this; }
|
|
2460
|
+
static {
|
|
2461
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2462
|
+
_id_decorators = [bindable];
|
|
2463
|
+
_url_decorators = [bindable()];
|
|
2464
|
+
_color_decorators = [bindable()];
|
|
2465
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
2466
|
+
__esDecorate(null, null, _url_decorators, { kind: "field", name: "url", static: false, private: false, access: { has: obj => "url" in obj, get: obj => obj.url, set: (obj, value) => { obj.url = value; } }, metadata: _metadata }, _url_initializers, _url_extraInitializers);
|
|
2467
|
+
__esDecorate(null, null, _color_decorators, { kind: "field", name: "color", static: false, private: false, access: { has: obj => "color" in obj, get: obj => obj.color, set: (obj, value) => { obj.color = value; } }, metadata: _metadata }, _color_initializers, _color_extraInitializers);
|
|
2468
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2469
|
+
_classThis = _classDescriptor.value;
|
|
2470
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2471
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2472
|
+
}
|
|
2473
|
+
logger;
|
|
2474
|
+
element;
|
|
2475
|
+
ea;
|
|
2476
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
2477
|
+
url = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _url_initializers, ''));
|
|
2478
|
+
color = (__runInitializers(this, _url_extraInitializers), __runInitializers(this, _color_initializers, 'primary'));
|
|
2479
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-modal-trigger'), element = resolve(INode), ea = resolve(IEventAggregator)) {
|
|
2480
|
+
this.logger = logger;
|
|
2481
|
+
this.element = element;
|
|
2482
|
+
this.ea = ea;
|
|
2483
|
+
this.logger.trace('constructor');
|
|
2484
|
+
}
|
|
2485
|
+
attaching() {
|
|
2486
|
+
this.logger.trace('attaching');
|
|
2487
|
+
}
|
|
2488
|
+
attached() {
|
|
2489
|
+
this.logger.trace('attached');
|
|
2490
|
+
this.element.addEventListener('click', this.onClick);
|
|
2491
|
+
}
|
|
2492
|
+
detached() {
|
|
2493
|
+
this.logger.trace('detached');
|
|
2494
|
+
this.element.removeEventListener('click', this.onClick);
|
|
2495
|
+
}
|
|
2496
|
+
dispose() {
|
|
2497
|
+
this.logger.trace('dispose');
|
|
2498
|
+
}
|
|
2499
|
+
onClick = (__runInitializers(this, _color_extraInitializers), (event) => {
|
|
2500
|
+
this.logger.trace('onClick', event);
|
|
2501
|
+
event.preventDefault();
|
|
2502
|
+
this.ea.publish(Channels.Modal, {
|
|
2503
|
+
action: ModalAction.Toggle,
|
|
2504
|
+
id: this.id,
|
|
2505
|
+
url: this.url,
|
|
2506
|
+
color: this.color,
|
|
2507
|
+
});
|
|
2508
|
+
});
|
|
2509
|
+
});
|
|
2510
|
+
return _classThis;
|
|
2511
|
+
})();
|
|
2512
|
+
|
|
2513
|
+
let BleetPagerCustomAttribute = (() => {
|
|
2514
|
+
let _classDecorators = [customAttribute('bleet-pager')];
|
|
2515
|
+
let _classDescriptor;
|
|
2516
|
+
let _classExtraInitializers = [];
|
|
2517
|
+
let _classThis;
|
|
2518
|
+
(class {
|
|
2519
|
+
static { _classThis = this; }
|
|
2520
|
+
static {
|
|
2521
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2522
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2523
|
+
_classThis = _classDescriptor.value;
|
|
2524
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2525
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2526
|
+
}
|
|
2527
|
+
logger;
|
|
2528
|
+
element;
|
|
2529
|
+
p;
|
|
2530
|
+
select;
|
|
2531
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-pager'), element = resolve(INode), p = resolve(IPlatform)) {
|
|
2532
|
+
this.logger = logger;
|
|
2533
|
+
this.element = element;
|
|
2534
|
+
this.p = p;
|
|
2535
|
+
this.logger.trace('constructor');
|
|
2536
|
+
}
|
|
2537
|
+
attaching() {
|
|
2538
|
+
this.logger.trace('attaching');
|
|
2539
|
+
this.select = this.element.querySelector('[data-pager="select"]');
|
|
2540
|
+
}
|
|
2541
|
+
attached() {
|
|
2542
|
+
this.logger.trace('attached');
|
|
2543
|
+
this.select?.addEventListener('change', this.onChangeSelect);
|
|
2544
|
+
}
|
|
2545
|
+
detached() {
|
|
2546
|
+
this.logger.trace('detached');
|
|
2547
|
+
this.select?.removeEventListener('change', this.onChangeSelect);
|
|
2548
|
+
}
|
|
2549
|
+
onChangeSelect = (event) => {
|
|
2550
|
+
this.logger.trace('onChangeSelect', event);
|
|
2551
|
+
const pageNumber = this.select?.value;
|
|
2552
|
+
const link = this.element.querySelector(`[data-pager="page-${pageNumber}"]`);
|
|
2553
|
+
if (link) {
|
|
2554
|
+
link.click();
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
});
|
|
2558
|
+
return _classThis;
|
|
2559
|
+
})();
|
|
2560
|
+
|
|
2561
|
+
let BleetUploadCustomAttribute = (() => {
|
|
2562
|
+
let _classDecorators = [customAttribute({ name: 'bleet-upload', defaultProperty: 'endpoint' })];
|
|
2563
|
+
let _classDescriptor;
|
|
2564
|
+
let _classExtraInitializers = [];
|
|
2565
|
+
let _classThis;
|
|
2566
|
+
let _endpoint_decorators;
|
|
2567
|
+
let _endpoint_initializers = [];
|
|
2568
|
+
let _endpoint_extraInitializers = [];
|
|
2569
|
+
let _previewEndpoint_decorators;
|
|
2570
|
+
let _previewEndpoint_initializers = [];
|
|
2571
|
+
let _previewEndpoint_extraInitializers = [];
|
|
2572
|
+
let _deleteEndpoint_decorators;
|
|
2573
|
+
let _deleteEndpoint_initializers = [];
|
|
2574
|
+
let _deleteEndpoint_extraInitializers = [];
|
|
2575
|
+
let _accept_decorators;
|
|
2576
|
+
let _accept_initializers = [];
|
|
2577
|
+
let _accept_extraInitializers = [];
|
|
2578
|
+
let _maxFiles_decorators;
|
|
2579
|
+
let _maxFiles_initializers = [];
|
|
2580
|
+
let _maxFiles_extraInitializers = [];
|
|
2581
|
+
let _multiple_decorators;
|
|
2582
|
+
let _multiple_initializers = [];
|
|
2583
|
+
let _multiple_extraInitializers = [];
|
|
2584
|
+
let _chunkSize_decorators;
|
|
2585
|
+
let _chunkSize_initializers = [];
|
|
2586
|
+
let _chunkSize_extraInitializers = [];
|
|
2587
|
+
(class {
|
|
2588
|
+
static { _classThis = this; }
|
|
2589
|
+
static {
|
|
2590
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2591
|
+
_endpoint_decorators = [bindable];
|
|
2592
|
+
_previewEndpoint_decorators = [bindable()];
|
|
2593
|
+
_deleteEndpoint_decorators = [bindable()];
|
|
2594
|
+
_accept_decorators = [bindable()];
|
|
2595
|
+
_maxFiles_decorators = [bindable()];
|
|
2596
|
+
_multiple_decorators = [bindable()];
|
|
2597
|
+
_chunkSize_decorators = [bindable()];
|
|
2598
|
+
__esDecorate(null, null, _endpoint_decorators, { kind: "field", name: "endpoint", static: false, private: false, access: { has: obj => "endpoint" in obj, get: obj => obj.endpoint, set: (obj, value) => { obj.endpoint = value; } }, metadata: _metadata }, _endpoint_initializers, _endpoint_extraInitializers);
|
|
2599
|
+
__esDecorate(null, null, _previewEndpoint_decorators, { kind: "field", name: "previewEndpoint", static: false, private: false, access: { has: obj => "previewEndpoint" in obj, get: obj => obj.previewEndpoint, set: (obj, value) => { obj.previewEndpoint = value; } }, metadata: _metadata }, _previewEndpoint_initializers, _previewEndpoint_extraInitializers);
|
|
2600
|
+
__esDecorate(null, null, _deleteEndpoint_decorators, { kind: "field", name: "deleteEndpoint", static: false, private: false, access: { has: obj => "deleteEndpoint" in obj, get: obj => obj.deleteEndpoint, set: (obj, value) => { obj.deleteEndpoint = value; } }, metadata: _metadata }, _deleteEndpoint_initializers, _deleteEndpoint_extraInitializers);
|
|
2601
|
+
__esDecorate(null, null, _accept_decorators, { kind: "field", name: "accept", static: false, private: false, access: { has: obj => "accept" in obj, get: obj => obj.accept, set: (obj, value) => { obj.accept = value; } }, metadata: _metadata }, _accept_initializers, _accept_extraInitializers);
|
|
2602
|
+
__esDecorate(null, null, _maxFiles_decorators, { kind: "field", name: "maxFiles", static: false, private: false, access: { has: obj => "maxFiles" in obj, get: obj => obj.maxFiles, set: (obj, value) => { obj.maxFiles = value; } }, metadata: _metadata }, _maxFiles_initializers, _maxFiles_extraInitializers);
|
|
2603
|
+
__esDecorate(null, null, _multiple_decorators, { kind: "field", name: "multiple", static: false, private: false, access: { has: obj => "multiple" in obj, get: obj => obj.multiple, set: (obj, value) => { obj.multiple = value; } }, metadata: _metadata }, _multiple_initializers, _multiple_extraInitializers);
|
|
2604
|
+
__esDecorate(null, null, _chunkSize_decorators, { kind: "field", name: "chunkSize", static: false, private: false, access: { has: obj => "chunkSize" in obj, get: obj => obj.chunkSize, set: (obj, value) => { obj.chunkSize = value; } }, metadata: _metadata }, _chunkSize_initializers, _chunkSize_extraInitializers);
|
|
2605
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2606
|
+
_classThis = _classDescriptor.value;
|
|
2607
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2608
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2609
|
+
}
|
|
2610
|
+
logger;
|
|
2611
|
+
element;
|
|
2612
|
+
ea;
|
|
2613
|
+
endpoint = __runInitializers(this, _endpoint_initializers, '');
|
|
2614
|
+
previewEndpoint = (__runInitializers(this, _endpoint_extraInitializers), __runInitializers(this, _previewEndpoint_initializers, ''));
|
|
2615
|
+
deleteEndpoint = (__runInitializers(this, _previewEndpoint_extraInitializers), __runInitializers(this, _deleteEndpoint_initializers, ''));
|
|
2616
|
+
accept = (__runInitializers(this, _deleteEndpoint_extraInitializers), __runInitializers(this, _accept_initializers, ''));
|
|
2617
|
+
maxFiles = (__runInitializers(this, _accept_extraInitializers), __runInitializers(this, _maxFiles_initializers, 1));
|
|
2618
|
+
multiple = (__runInitializers(this, _maxFiles_extraInitializers), __runInitializers(this, _multiple_initializers, false));
|
|
2619
|
+
chunkSize = (__runInitializers(this, _multiple_extraInitializers), __runInitializers(this, _chunkSize_initializers, 512 * 1024));
|
|
2620
|
+
resumable = (__runInitializers(this, _chunkSize_extraInitializers), null);
|
|
2621
|
+
dropzone = null;
|
|
2622
|
+
browseButton = null;
|
|
2623
|
+
fileList = null;
|
|
2624
|
+
hiddenInput = null;
|
|
2625
|
+
previewTemplate = null;
|
|
2626
|
+
handledFiles = [];
|
|
2627
|
+
parentForm = null;
|
|
2628
|
+
csrfToken = null;
|
|
2629
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-upload'), element = resolve(INode), ea = resolve(IEventAggregator)) {
|
|
2630
|
+
this.logger = logger;
|
|
2631
|
+
this.element = element;
|
|
2632
|
+
this.ea = ea;
|
|
2633
|
+
this.logger.trace('constructor');
|
|
2634
|
+
}
|
|
2635
|
+
attaching() {
|
|
2636
|
+
this.dropzone = this.element.querySelector('[data-upload=dropzone]');
|
|
2637
|
+
this.browseButton = this.element.querySelector('[data-upload=browse]');
|
|
2638
|
+
this.fileList = this.element.querySelector('[data-upload=list]');
|
|
2639
|
+
this.hiddenInput = this.element.querySelector('[data-upload=value]');
|
|
2640
|
+
this.previewTemplate = this.element.querySelector('[data-upload=preview-template]');
|
|
2641
|
+
}
|
|
2642
|
+
attached() {
|
|
2643
|
+
if (!this.endpoint || !this.dropzone) {
|
|
2644
|
+
this.logger.warn('Missing endpoint or dropzone');
|
|
2645
|
+
return;
|
|
2646
|
+
}
|
|
2647
|
+
if (this.element.hasAttribute('data-disabled')) {
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
this.parentForm = this.element.closest('form');
|
|
2651
|
+
this.extractCsrfToken();
|
|
2652
|
+
this.initResumable();
|
|
2653
|
+
this.setFiles(this.hiddenInput?.value || '');
|
|
2654
|
+
}
|
|
2655
|
+
detaching() {
|
|
2656
|
+
if (this.resumable && this.dropzone) {
|
|
2657
|
+
this.dropzone.removeEventListener('dragover', this.onDragEnter);
|
|
2658
|
+
this.dropzone.removeEventListener('dragenter', this.onDragEnter);
|
|
2659
|
+
this.dropzone.removeEventListener('dragleave', this.onDragLeave);
|
|
2660
|
+
this.dropzone.removeEventListener('drop', this.onDragLeave);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
extractCsrfToken() {
|
|
2664
|
+
if (!this.parentForm)
|
|
2665
|
+
return;
|
|
2666
|
+
const csrfInput = this.parentForm.querySelector('input[name=_csrf]');
|
|
2667
|
+
if (csrfInput) {
|
|
2668
|
+
this.csrfToken = {
|
|
2669
|
+
name: csrfInput.name,
|
|
2670
|
+
value: csrfInput.value
|
|
2671
|
+
};
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
initResumable() {
|
|
2675
|
+
const resumableConfig = {
|
|
2676
|
+
target: this.endpoint,
|
|
2677
|
+
chunkSize: this.chunkSize,
|
|
2678
|
+
simultaneousUploads: 3,
|
|
2679
|
+
permanentErrors: [400, 404, 415, 422, 500, 501],
|
|
2680
|
+
maxChunkRetries: 0
|
|
2681
|
+
};
|
|
2682
|
+
if (this.accept) {
|
|
2683
|
+
const fileTypes = this.accept.split(/\s*,\s*/).filter(v => v.trim() !== '');
|
|
2684
|
+
resumableConfig.fileType = fileTypes;
|
|
2685
|
+
resumableConfig.fileTypeErrorCallback = (file) => {
|
|
2686
|
+
this.showErrorToast(`Le fichier "${file.fileName}" n'est pas un type autorise (${fileTypes.map(t => t.toUpperCase()).join(', ')})`);
|
|
2687
|
+
};
|
|
2688
|
+
}
|
|
2689
|
+
if (this.csrfToken) {
|
|
2690
|
+
resumableConfig.headers = {
|
|
2691
|
+
'X-CSRF-Token': this.csrfToken.value
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
this.resumable = new Resumable(resumableConfig);
|
|
2695
|
+
if (!this.resumable.support) {
|
|
2696
|
+
this.logger.warn('Resumable.js not supported');
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
if (this.browseButton) {
|
|
2700
|
+
this.resumable.assignBrowse(this.browseButton, false);
|
|
2701
|
+
}
|
|
2702
|
+
if (this.dropzone) {
|
|
2703
|
+
this.resumable.assignDrop(this.dropzone);
|
|
2704
|
+
this.dropzone.addEventListener('dragover', this.onDragEnter);
|
|
2705
|
+
this.dropzone.addEventListener('dragenter', this.onDragEnter);
|
|
2706
|
+
this.dropzone.addEventListener('dragleave', this.onDragLeave);
|
|
2707
|
+
this.dropzone.addEventListener('drop', this.onDragLeave);
|
|
2708
|
+
}
|
|
2709
|
+
this.resumable.on('fileAdded', this.onFileAdded);
|
|
2710
|
+
this.resumable.on('fileSuccess', this.onFileSuccess);
|
|
2711
|
+
this.resumable.on('fileError', this.onFileError);
|
|
2712
|
+
}
|
|
2713
|
+
/**
|
|
2714
|
+
* Charge les fichiers depuis une valeur (initialisation)
|
|
2715
|
+
*/
|
|
2716
|
+
setFiles(value) {
|
|
2717
|
+
const files = value.split(/\s*,\s*/).filter(v => v.trim() !== '');
|
|
2718
|
+
this.handledFiles = files.map(name => ({
|
|
2719
|
+
name,
|
|
2720
|
+
shortname: name.split(/.*[\/|\\]/).pop(),
|
|
2721
|
+
previewUrl: this.generatePreviewUrl(name),
|
|
2722
|
+
deleteUrl: this.generateDeleteUrl(name)
|
|
2723
|
+
}));
|
|
2724
|
+
this.renderFileList();
|
|
2725
|
+
this.updateHiddenInput();
|
|
2726
|
+
}
|
|
2727
|
+
/**
|
|
2728
|
+
* Remplace tous les fichiers par un seul (mode single)
|
|
2729
|
+
*/
|
|
2730
|
+
setFile(name, file = null) {
|
|
2731
|
+
// Supprimer les anciens fichiers temporaires
|
|
2732
|
+
this.handledFiles.forEach(f => {
|
|
2733
|
+
if (f.file && this.resumable) {
|
|
2734
|
+
this.resumable.removeFile(f.file);
|
|
2735
|
+
}
|
|
2736
|
+
this.deleteFileOnServer(f.name);
|
|
2737
|
+
});
|
|
2738
|
+
this.handledFiles = [{
|
|
2739
|
+
name,
|
|
2740
|
+
shortname: name.split(/.*[\/|\\]/).pop(),
|
|
2741
|
+
previewUrl: this.generatePreviewUrl(name),
|
|
2742
|
+
deleteUrl: this.generateDeleteUrl(name),
|
|
2743
|
+
file
|
|
2744
|
+
}];
|
|
2745
|
+
this.renderFileList();
|
|
2746
|
+
this.updateHiddenInput();
|
|
2747
|
+
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Ajoute un fichier (mode multiple)
|
|
2750
|
+
*/
|
|
2751
|
+
appendFile(name, file = null) {
|
|
2752
|
+
this.handledFiles.push({
|
|
2753
|
+
name,
|
|
2754
|
+
shortname: name.split(/.*[\/|\\]/).pop(),
|
|
2755
|
+
previewUrl: this.generatePreviewUrl(name),
|
|
2756
|
+
deleteUrl: this.generateDeleteUrl(name),
|
|
2757
|
+
file
|
|
2758
|
+
});
|
|
2759
|
+
this.renderFileList();
|
|
2760
|
+
this.updateHiddenInput();
|
|
2761
|
+
}
|
|
2762
|
+
/**
|
|
2763
|
+
* Supprime un fichier
|
|
2764
|
+
*/
|
|
2765
|
+
onRemove(handledFile, evt) {
|
|
2766
|
+
evt.stopPropagation();
|
|
2767
|
+
evt.preventDefault();
|
|
2768
|
+
const index = this.handledFiles.findIndex(f => f.name === handledFile.name);
|
|
2769
|
+
if (index === -1)
|
|
2770
|
+
return;
|
|
2771
|
+
if (handledFile.file && this.resumable) {
|
|
2772
|
+
this.resumable.removeFile(handledFile.file);
|
|
2773
|
+
}
|
|
2774
|
+
this.deleteFileOnServer(handledFile.name);
|
|
2775
|
+
this.handledFiles.splice(index, 1);
|
|
2776
|
+
this.renderFileList();
|
|
2777
|
+
this.updateHiddenInput();
|
|
2778
|
+
}
|
|
2779
|
+
deleteFileOnServer(name) {
|
|
2780
|
+
// Ne supprimer que les fichiers temporaires
|
|
2781
|
+
if (!name || !name.startsWith('@bltmp/'))
|
|
2782
|
+
return;
|
|
2783
|
+
const deleteUrl = this.generateDeleteUrl(name);
|
|
2784
|
+
if (!deleteUrl)
|
|
2785
|
+
return;
|
|
2786
|
+
fetch(deleteUrl, {
|
|
2787
|
+
method: 'DELETE',
|
|
2788
|
+
headers: this.csrfToken ? {
|
|
2789
|
+
'X-CSRF-Token': this.csrfToken.value
|
|
2790
|
+
} : {}
|
|
2791
|
+
}).catch(e => this.logger.error('Delete failed', e));
|
|
2792
|
+
}
|
|
2793
|
+
generatePreviewUrl(name) {
|
|
2794
|
+
if (!this.previewEndpoint)
|
|
2795
|
+
return '';
|
|
2796
|
+
return this.previewEndpoint.replace('__name__', encodeURIComponent(name));
|
|
2797
|
+
}
|
|
2798
|
+
generateDeleteUrl(name) {
|
|
2799
|
+
if (!this.deleteEndpoint)
|
|
2800
|
+
return '';
|
|
2801
|
+
return this.deleteEndpoint.replace('__name__', encodeURIComponent(name));
|
|
2802
|
+
}
|
|
2803
|
+
updateHiddenInput() {
|
|
2804
|
+
if (!this.hiddenInput)
|
|
2805
|
+
return;
|
|
2806
|
+
this.hiddenInput.value = this.handledFiles.map(f => f.name).join(', ');
|
|
2807
|
+
this.hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));
|
|
2808
|
+
}
|
|
2809
|
+
renderFileList() {
|
|
2810
|
+
if (!this.fileList || !this.previewTemplate)
|
|
2811
|
+
return;
|
|
2812
|
+
this.fileList.innerHTML = '';
|
|
2813
|
+
this.handledFiles.forEach(handledFile => {
|
|
2814
|
+
const fragment = this.previewTemplate.content.cloneNode(true);
|
|
2815
|
+
const item = fragment.firstElementChild;
|
|
2816
|
+
// Preview link
|
|
2817
|
+
const previewLink = item.querySelector('[data-upload=preview-link]');
|
|
2818
|
+
if (previewLink) {
|
|
2819
|
+
previewLink.href = handledFile.previewUrl ? `${handledFile.previewUrl}&original=1` : '#';
|
|
2820
|
+
}
|
|
2821
|
+
// Preview image et icon
|
|
2822
|
+
const previewImage = item.querySelector('[data-upload=preview-image]');
|
|
2823
|
+
const previewIcon = item.querySelector('[data-upload=preview-icon]');
|
|
2824
|
+
if (handledFile.previewUrl) {
|
|
2825
|
+
this.loadPreview(previewImage, previewIcon, handledFile);
|
|
2826
|
+
}
|
|
2827
|
+
// Si pas de previewUrl, l'icône reste visible (hidden est sur l'image par défaut)
|
|
2828
|
+
// Nom du fichier
|
|
2829
|
+
const nameEl = item.querySelector('[data-upload=preview-name]');
|
|
2830
|
+
if (nameEl) {
|
|
2831
|
+
nameEl.textContent = handledFile.shortname || '';
|
|
2832
|
+
}
|
|
2833
|
+
// Bouton supprimer
|
|
2834
|
+
const removeBtn = item.querySelector('[data-upload=preview-remove]');
|
|
2835
|
+
if (removeBtn) {
|
|
2836
|
+
removeBtn.addEventListener('click', (e) => this.onRemove(handledFile, e));
|
|
2837
|
+
}
|
|
2838
|
+
this.fileList.appendChild(fragment);
|
|
2839
|
+
});
|
|
2840
|
+
}
|
|
2841
|
+
loadPreview(previewImage, previewIcon, handledFile) {
|
|
2842
|
+
const shortname = handledFile.shortname || '';
|
|
2843
|
+
if (shortname.toLowerCase().endsWith('.svg')) {
|
|
2844
|
+
// SVG : fetch et inline dans le container parent (le lien)
|
|
2845
|
+
fetch(handledFile.previewUrl)
|
|
2846
|
+
.then(response => {
|
|
2847
|
+
if (!response.ok)
|
|
2848
|
+
throw new Error('Failed to load SVG');
|
|
2849
|
+
return response.text();
|
|
2850
|
+
})
|
|
2851
|
+
.then(svgContent => {
|
|
2852
|
+
// Cacher l'icône par défaut
|
|
2853
|
+
previewIcon.classList.add('hidden');
|
|
2854
|
+
// Insérer le SVG à la place de l'image
|
|
2855
|
+
previewImage.insertAdjacentHTML('afterend', svgContent);
|
|
2856
|
+
const svg = previewImage.parentElement?.querySelector('svg:not([data-upload])');
|
|
2857
|
+
if (svg) {
|
|
2858
|
+
svg.classList.add('size-full');
|
|
2859
|
+
svg.removeAttribute('width');
|
|
2860
|
+
svg.removeAttribute('height');
|
|
2861
|
+
}
|
|
2862
|
+
})
|
|
2863
|
+
.catch(() => {
|
|
2864
|
+
// Garder l'icône visible en cas d'erreur
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
else {
|
|
2868
|
+
// Autres fichiers : utiliser l'image du template
|
|
2869
|
+
previewImage.src = handledFile.previewUrl;
|
|
2870
|
+
previewImage.alt = shortname;
|
|
2871
|
+
previewImage.onload = () => {
|
|
2872
|
+
previewImage.classList.remove('hidden');
|
|
2873
|
+
previewIcon.classList.add('hidden');
|
|
2874
|
+
};
|
|
2875
|
+
previewImage.onerror = () => {
|
|
2876
|
+
// Garder l'icône visible en cas d'erreur
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
showErrorToast(message) {
|
|
2881
|
+
this.ea.publish(Channels.Toaster, {
|
|
2882
|
+
action: ToasterAction.Add,
|
|
2883
|
+
toast: {
|
|
2884
|
+
id: `upload-error-${Date.now()}`,
|
|
2885
|
+
duration: 5000,
|
|
2886
|
+
color: UiColor.Danger,
|
|
2887
|
+
icon: UiToastIcon.Danger,
|
|
2888
|
+
title: 'Erreur',
|
|
2889
|
+
content: message
|
|
2890
|
+
}
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
// Resumable.js event handlers
|
|
2894
|
+
onDragEnter = (evt) => {
|
|
2895
|
+
evt.preventDefault();
|
|
2896
|
+
const dt = evt.dataTransfer;
|
|
2897
|
+
if (dt && dt.types.indexOf('Files') >= 0) {
|
|
2898
|
+
evt.stopPropagation();
|
|
2899
|
+
dt.dropEffect = 'copy';
|
|
2900
|
+
this.dropzone?.classList.add('border-primary-600', 'bg-primary-50');
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
onDragLeave = (evt) => {
|
|
2904
|
+
this.dropzone?.classList.remove('border-primary-600', 'bg-primary-50');
|
|
2905
|
+
};
|
|
2906
|
+
onFileAdded = (file, event) => {
|
|
2907
|
+
this.logger.debug('onFileAdded', file.fileName);
|
|
2908
|
+
this.resumable?.upload();
|
|
2909
|
+
};
|
|
2910
|
+
onFileSuccess = (file, serverMessage) => {
|
|
2911
|
+
this.logger.debug('onFileSuccess', file.fileName, serverMessage);
|
|
2912
|
+
try {
|
|
2913
|
+
const response = JSON.parse(serverMessage);
|
|
2914
|
+
if (!response.finalFilename) {
|
|
2915
|
+
throw new Error('Missing finalFilename in response');
|
|
2916
|
+
}
|
|
2917
|
+
const finalName = `@bltmp/${response.finalFilename}`;
|
|
2918
|
+
if (!this.multiple) {
|
|
2919
|
+
this.setFile(finalName, file);
|
|
2920
|
+
}
|
|
2921
|
+
else {
|
|
2922
|
+
this.appendFile(finalName, file);
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
catch (e) {
|
|
2926
|
+
this.logger.error('Failed to parse server response', e);
|
|
2927
|
+
this.showErrorToast('Reponse serveur invalide');
|
|
2928
|
+
}
|
|
2929
|
+
};
|
|
2930
|
+
onFileError = (file, message) => {
|
|
2931
|
+
this.logger.error('onFileError', file.fileName, message);
|
|
2932
|
+
this.showErrorToast(`Echec de l'upload de "${file.fileName}"`);
|
|
2933
|
+
};
|
|
2934
|
+
});
|
|
2935
|
+
return _classThis;
|
|
2936
|
+
})();
|
|
2937
|
+
|
|
2938
|
+
/**
|
|
2939
|
+
* Generic AJAX trigger attribute for elements.
|
|
2940
|
+
* Placed on the element that triggers the AJAX call.
|
|
2941
|
+
* Looks up parent form with closest() to get URL/verb if not specified.
|
|
2942
|
+
* Sends only the inputs contained within this.element.
|
|
2943
|
+
* Pessimistic UI: state changes only on server response.
|
|
2944
|
+
*
|
|
2945
|
+
* Bindables:
|
|
2946
|
+
* - url (primary): URL to call. Falls back to closest form.action.
|
|
2947
|
+
* - verb: HTTP method. Falls back to closest form.method or 'POST'.
|
|
2948
|
+
* - event: DOM event to listen for (default: 'click')
|
|
2949
|
+
* - collect: If set, also collects inputs with data-ajaxify="{collect}" from closest form
|
|
2950
|
+
*/
|
|
2951
|
+
let BleetAjaxifyTriggerCustomAttribute = (() => {
|
|
2952
|
+
let _classDecorators = [customAttribute({ name: 'bleet-ajaxify-trigger', defaultProperty: 'url' })];
|
|
2953
|
+
let _classDescriptor;
|
|
2954
|
+
let _classExtraInitializers = [];
|
|
2955
|
+
let _classThis;
|
|
2956
|
+
let _url_decorators;
|
|
2957
|
+
let _url_initializers = [];
|
|
2958
|
+
let _url_extraInitializers = [];
|
|
2959
|
+
let _verb_decorators;
|
|
2960
|
+
let _verb_initializers = [];
|
|
2961
|
+
let _verb_extraInitializers = [];
|
|
2962
|
+
let _event_decorators;
|
|
2963
|
+
let _event_initializers = [];
|
|
2964
|
+
let _event_extraInitializers = [];
|
|
2965
|
+
let _id_decorators;
|
|
2966
|
+
let _id_initializers = [];
|
|
2967
|
+
let _id_extraInitializers = [];
|
|
2968
|
+
(class {
|
|
2969
|
+
static { _classThis = this; }
|
|
2970
|
+
static {
|
|
2971
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
2972
|
+
_url_decorators = [bindable];
|
|
2973
|
+
_verb_decorators = [bindable()];
|
|
2974
|
+
_event_decorators = [bindable()];
|
|
2975
|
+
_id_decorators = [bindable()];
|
|
2976
|
+
__esDecorate(null, null, _url_decorators, { kind: "field", name: "url", static: false, private: false, access: { has: obj => "url" in obj, get: obj => obj.url, set: (obj, value) => { obj.url = value; } }, metadata: _metadata }, _url_initializers, _url_extraInitializers);
|
|
2977
|
+
__esDecorate(null, null, _verb_decorators, { kind: "field", name: "verb", static: false, private: false, access: { has: obj => "verb" in obj, get: obj => obj.verb, set: (obj, value) => { obj.verb = value; } }, metadata: _metadata }, _verb_initializers, _verb_extraInitializers);
|
|
2978
|
+
__esDecorate(null, null, _event_decorators, { kind: "field", name: "event", static: false, private: false, access: { has: obj => "event" in obj, get: obj => obj.event, set: (obj, value) => { obj.event = value; } }, metadata: _metadata }, _event_initializers, _event_extraInitializers);
|
|
2979
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
2980
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2981
|
+
_classThis = _classDescriptor.value;
|
|
2982
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2983
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
2984
|
+
}
|
|
2985
|
+
logger;
|
|
2986
|
+
element;
|
|
2987
|
+
ea;
|
|
2988
|
+
apiService;
|
|
2989
|
+
url = __runInitializers(this, _url_initializers, '');
|
|
2990
|
+
verb = (__runInitializers(this, _url_extraInitializers), __runInitializers(this, _verb_initializers, ''));
|
|
2991
|
+
event = (__runInitializers(this, _verb_extraInitializers), __runInitializers(this, _event_initializers, 'click'));
|
|
2992
|
+
id = (__runInitializers(this, _event_extraInitializers), __runInitializers(this, _id_initializers, ''));
|
|
2993
|
+
constructor(logger = resolve(ILogger).scopeTo('bleet-ajaxify-trigger'), element = resolve(INode), ea = resolve(IEventAggregator), apiService = resolve(IApiService)) {
|
|
2994
|
+
this.logger = logger;
|
|
2995
|
+
this.element = element;
|
|
2996
|
+
this.ea = ea;
|
|
2997
|
+
this.apiService = apiService;
|
|
2998
|
+
this.logger.trace('constructor');
|
|
2999
|
+
}
|
|
3000
|
+
attached() {
|
|
3001
|
+
this.logger.trace('attached', { url: this.url, verb: this.verb, event: this.event });
|
|
3002
|
+
this.element.addEventListener(this.event, this.onTrigger);
|
|
3003
|
+
}
|
|
3004
|
+
detached() {
|
|
3005
|
+
this.logger.trace('detached');
|
|
3006
|
+
this.element.removeEventListener(this.event, this.onTrigger);
|
|
3007
|
+
}
|
|
3008
|
+
onTrigger = (__runInitializers(this, _id_extraInitializers), (event) => {
|
|
3009
|
+
event.preventDefault();
|
|
3010
|
+
event.stopPropagation();
|
|
3011
|
+
this.logger.trace('onTrigger', event);
|
|
3012
|
+
const form = this.element.closest('form');
|
|
3013
|
+
const url = this.resolveUrl(form);
|
|
3014
|
+
const verb = this.resolveVerb(form);
|
|
3015
|
+
if (!url) {
|
|
3016
|
+
this.logger.warn('No URL found for ajaxify-trigger');
|
|
3017
|
+
return;
|
|
3018
|
+
}
|
|
3019
|
+
this.logger.debug('onTrigger', { url, verb });
|
|
3020
|
+
// Build FormData from inputs INSIDE this.element only
|
|
3021
|
+
const formData = this.buildFormData(event);
|
|
3022
|
+
this.apiService
|
|
3023
|
+
.url(url)
|
|
3024
|
+
.fromMultipart(formData)
|
|
3025
|
+
.request(verb)
|
|
3026
|
+
.then((response) => {
|
|
3027
|
+
this.logger.debug('response', response.body);
|
|
3028
|
+
// Update element from response HTML
|
|
3029
|
+
if (response.body.element) {
|
|
3030
|
+
this.updateElement(response.body.element);
|
|
3031
|
+
}
|
|
3032
|
+
// Show toast if provided
|
|
3033
|
+
if (response.body.toast) {
|
|
3034
|
+
this.ea.publish(Channels.Toaster, {
|
|
3035
|
+
action: ToasterAction.Add,
|
|
3036
|
+
toast: response.body.toast
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
// Trigger ajaxify refresh if provided
|
|
3040
|
+
if (response.body.ajaxify) {
|
|
3041
|
+
this.ea.publish(Channels.Ajaxify, response.body.ajaxify);
|
|
3042
|
+
}
|
|
3043
|
+
})
|
|
3044
|
+
.catch((error) => {
|
|
3045
|
+
this.logger.error('AJAX request failed', error);
|
|
3046
|
+
this.ea.publish(Channels.Toaster, {
|
|
3047
|
+
action: ToasterAction.Add,
|
|
3048
|
+
toast: {
|
|
3049
|
+
color: UiColor.Danger,
|
|
3050
|
+
title: 'Erreur',
|
|
3051
|
+
content: 'Une erreur est survenue.',
|
|
3052
|
+
duration: 5000,
|
|
3053
|
+
}
|
|
3054
|
+
});
|
|
3055
|
+
});
|
|
3056
|
+
});
|
|
3057
|
+
buildFormData(event) {
|
|
3058
|
+
const formData = new FormData();
|
|
3059
|
+
// Get all inputs inside this.element
|
|
3060
|
+
const inputs = this.element.querySelectorAll('input, select, textarea');
|
|
3061
|
+
this.appendInputsToFormData(formData, inputs);
|
|
3062
|
+
// Capture submitter button name/value (for submit events)
|
|
3063
|
+
if (event instanceof SubmitEvent && event.submitter) {
|
|
3064
|
+
const submitter = event.submitter;
|
|
3065
|
+
if (submitter.name) {
|
|
3066
|
+
formData.append(submitter.name, submitter.value || '');
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
// Also get CSRF token from parent form if exists
|
|
3070
|
+
const form = this.element.closest('form');
|
|
3071
|
+
if (form) {
|
|
3072
|
+
const csrfInput = form.querySelector('input[name="_csrf"]');
|
|
3073
|
+
if (csrfInput) {
|
|
3074
|
+
formData.append('_csrf', csrfInput.value);
|
|
3075
|
+
}
|
|
3076
|
+
// If id is set, also collect inputs with data-ajaxify="{id}" from the form
|
|
3077
|
+
if (this.id) {
|
|
3078
|
+
const ajaxifyInputs = form.querySelectorAll(`[data-ajaxify="${this.id}"]`);
|
|
3079
|
+
this.appendInputsToFormData(formData, ajaxifyInputs);
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
return formData;
|
|
3083
|
+
}
|
|
3084
|
+
appendInputsToFormData(formData, inputs) {
|
|
3085
|
+
for (const input of Array.from(inputs)) {
|
|
3086
|
+
if (input instanceof HTMLInputElement) {
|
|
3087
|
+
if (input.type === 'checkbox' || input.type === 'radio') {
|
|
3088
|
+
if (input.checked && input.name) {
|
|
3089
|
+
formData.append(input.name, input.value || 'on');
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
else if (input.name) {
|
|
3093
|
+
formData.append(input.name, input.value);
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
else if (input instanceof HTMLSelectElement && input.name) {
|
|
3097
|
+
formData.append(input.name, input.value);
|
|
3098
|
+
}
|
|
3099
|
+
else if (input instanceof HTMLTextAreaElement && input.name) {
|
|
3100
|
+
formData.append(input.name, input.value);
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
resolveUrl(form) {
|
|
3105
|
+
if (this.url) {
|
|
3106
|
+
return this.url;
|
|
3107
|
+
}
|
|
3108
|
+
if (form) {
|
|
3109
|
+
return form.action || '';
|
|
3110
|
+
}
|
|
3111
|
+
return '';
|
|
3112
|
+
}
|
|
3113
|
+
resolveVerb(form) {
|
|
3114
|
+
if (this.verb) {
|
|
3115
|
+
return this.verb;
|
|
3116
|
+
}
|
|
3117
|
+
if (form) {
|
|
3118
|
+
return form.method || 'POST';
|
|
3119
|
+
}
|
|
3120
|
+
return 'POST';
|
|
3121
|
+
}
|
|
3122
|
+
updateElement(html) {
|
|
3123
|
+
const template = document.createElement('template');
|
|
3124
|
+
template.innerHTML = html.trim();
|
|
3125
|
+
const newElement = template.content.firstElementChild;
|
|
3126
|
+
if (newElement) {
|
|
3127
|
+
this.syncElement(this.element, newElement);
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
syncElement(current, incoming) {
|
|
3131
|
+
// Sync attributes of current element
|
|
3132
|
+
for (const attr of Array.from(incoming.attributes)) {
|
|
3133
|
+
current.setAttribute(attr.name, attr.value);
|
|
3134
|
+
}
|
|
3135
|
+
// Remove attributes that don't exist in incoming
|
|
3136
|
+
for (const attr of Array.from(current.attributes)) {
|
|
3137
|
+
if (!incoming.hasAttribute(attr.name)) {
|
|
3138
|
+
current.removeAttribute(attr.name);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
// Sync input values for form elements
|
|
3142
|
+
if (current instanceof HTMLInputElement && incoming instanceof HTMLInputElement) {
|
|
3143
|
+
if (current.type === 'checkbox' || current.type === 'radio') {
|
|
3144
|
+
current.checked = incoming.checked;
|
|
3145
|
+
}
|
|
3146
|
+
else {
|
|
3147
|
+
current.value = incoming.value;
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
// Sync children recursively
|
|
3151
|
+
const currentChildren = Array.from(current.children);
|
|
3152
|
+
const incomingChildren = Array.from(incoming.children);
|
|
3153
|
+
for (let i = 0; i < incomingChildren.length; i++) {
|
|
3154
|
+
if (i < currentChildren.length) {
|
|
3155
|
+
this.syncElement(currentChildren[i], incomingChildren[i]);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
});
|
|
3160
|
+
return _classThis;
|
|
3161
|
+
})();
|
|
3162
|
+
|
|
3163
|
+
let BleetOverlay = (() => {
|
|
3164
|
+
let _classDecorators = [customElement({
|
|
3165
|
+
name: 'bleet-overlay',
|
|
3166
|
+
template: null,
|
|
3167
|
+
})];
|
|
3168
|
+
let _classDescriptor;
|
|
3169
|
+
let _classExtraInitializers = [];
|
|
3170
|
+
let _classThis;
|
|
3171
|
+
(class {
|
|
3172
|
+
static { _classThis = this; }
|
|
3173
|
+
static {
|
|
3174
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
3175
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
3176
|
+
_classThis = _classDescriptor.value;
|
|
3177
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
3178
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
3179
|
+
}
|
|
3180
|
+
logger;
|
|
3181
|
+
element;
|
|
3182
|
+
ea;
|
|
3183
|
+
platform;
|
|
3184
|
+
transitionService;
|
|
3185
|
+
disposable;
|
|
3186
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-overlay>'), element = resolve(INode), ea = resolve(IEventAggregator), platform = resolve(IPlatform), transitionService = resolve(ITransitionService)) {
|
|
3187
|
+
this.logger = logger;
|
|
3188
|
+
this.element = element;
|
|
3189
|
+
this.ea = ea;
|
|
3190
|
+
this.platform = platform;
|
|
3191
|
+
this.transitionService = transitionService;
|
|
3192
|
+
this.logger.trace('constructor');
|
|
3193
|
+
}
|
|
3194
|
+
attaching() {
|
|
3195
|
+
this.logger.trace('attaching');
|
|
3196
|
+
}
|
|
3197
|
+
attached() {
|
|
3198
|
+
this.logger.trace('attached');
|
|
3199
|
+
this.disposable = this.ea.subscribe(Channels.Overlay, this.onOverlayEvent);
|
|
3200
|
+
this.element.addEventListener('click', this.onClickOverlay);
|
|
3201
|
+
}
|
|
3202
|
+
detached() {
|
|
3203
|
+
this.logger.trace('detached');
|
|
3204
|
+
this.element.removeEventListener('click', this.onClickOverlay);
|
|
3205
|
+
this.disposable?.dispose();
|
|
3206
|
+
}
|
|
3207
|
+
dispose() {
|
|
3208
|
+
this.logger.trace('dispose');
|
|
3209
|
+
this.disposable?.dispose();
|
|
3210
|
+
}
|
|
3211
|
+
toggle(fromOverlay = false) {
|
|
3212
|
+
if (this.element.classList.contains('hidden')) {
|
|
3213
|
+
this.open(fromOverlay);
|
|
3214
|
+
}
|
|
3215
|
+
else {
|
|
3216
|
+
this.close(fromOverlay);
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
open(fromOverlay = false) {
|
|
3220
|
+
if (this.element.classList.contains('hidden')) {
|
|
3221
|
+
this.logger.trace('open');
|
|
3222
|
+
this.transitionService.run(this.element, (element) => {
|
|
3223
|
+
if (fromOverlay) {
|
|
3224
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Open });
|
|
3225
|
+
}
|
|
3226
|
+
this.ea.publish(Channels.OverlayStatus, { status: OverlayStatus.Opening });
|
|
3227
|
+
element.classList.remove('hidden');
|
|
3228
|
+
this.platform.requestAnimationFrame(() => {
|
|
3229
|
+
element.classList.remove('opacity-0');
|
|
3230
|
+
element.classList.add('opacity-100');
|
|
3231
|
+
});
|
|
3232
|
+
this.logger.trace('open before()');
|
|
3233
|
+
}, (element) => {
|
|
3234
|
+
this.ea.publish(Channels.OverlayStatus, { status: OverlayStatus.Opened });
|
|
3235
|
+
this.logger.trace('open after()');
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
close(fromOverlay = false) {
|
|
3240
|
+
if (!this.element.classList.contains('hidden')) {
|
|
3241
|
+
this.transitionService.run(this.element, (element) => {
|
|
3242
|
+
if (fromOverlay) {
|
|
3243
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
3244
|
+
}
|
|
3245
|
+
this.ea.publish(Channels.OverlayStatus, { status: OverlayStatus.Closing });
|
|
3246
|
+
element.classList.remove('opacity-100');
|
|
3247
|
+
element.classList.add('opacity-0');
|
|
3248
|
+
this.logger.trace('close before()');
|
|
3249
|
+
}, (element) => {
|
|
3250
|
+
element.classList.add('hidden');
|
|
3251
|
+
this.logger.trace('close after()');
|
|
3252
|
+
this.ea.publish(Channels.OverlayStatus, { status: OverlayStatus.Closed });
|
|
3253
|
+
});
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
onOverlayEvent = (data) => {
|
|
3257
|
+
if (data.action === OverlayAction.Open) {
|
|
3258
|
+
this.logger.trace('onOverlayEvent', data);
|
|
3259
|
+
this.open();
|
|
3260
|
+
}
|
|
3261
|
+
else if (data.action === OverlayAction.Close) {
|
|
3262
|
+
this.logger.trace('onOverlayEvent', data);
|
|
3263
|
+
this.close();
|
|
3264
|
+
}
|
|
3265
|
+
else if (data.action === OverlayAction.Toggle) {
|
|
3266
|
+
this.logger.trace('onOverlayEvent', data);
|
|
3267
|
+
this.toggle();
|
|
3268
|
+
}
|
|
3269
|
+
else {
|
|
3270
|
+
this.logger.trace('onOverlayEvent unhandled', data);
|
|
3271
|
+
}
|
|
3272
|
+
};
|
|
3273
|
+
onClickOverlay = (event) => {
|
|
3274
|
+
this.logger.trace('onClickOverlay', event);
|
|
3275
|
+
event.preventDefault();
|
|
3276
|
+
this.close(true);
|
|
3277
|
+
};
|
|
3278
|
+
});
|
|
3279
|
+
return _classThis;
|
|
3280
|
+
})();
|
|
3281
|
+
|
|
3282
|
+
var template$5 = `<template>
|
|
3283
|
+
<div class="rounded-md border-l-4 p-4 shadow-lg"
|
|
3284
|
+
class.bind="'border-'+color+'-300 bg-'+color+'-50'">
|
|
3285
|
+
<div class="flex">
|
|
3286
|
+
<div class="shrink-0">
|
|
3287
|
+
<svg class="size-5"
|
|
3288
|
+
class.bind="'text-'+color+'-500'"
|
|
3289
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3290
|
+
viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
|
|
3291
|
+
<path if.bind="icon == 'information-circle'" fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm8.706-1.442c1.146-.573 2.437.463 2.126 1.706l-.709 2.836.042-.02a.75.75 0 0 1 .67 1.34l-.04.022c-1.147.573-2.438-.463-2.127-1.706l.71-2.836-.042.02a.75.75 0 1 1-.671-1.34l.041-.022ZM12 9a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd"/>
|
|
3292
|
+
<path if.bind="icon == 'check-circle'" fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd"/>
|
|
3293
|
+
<path if.bind="icon == 'exclamation-triangle'" fill-rule="evenodd" d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z" clip-rule="evenodd"/>
|
|
3294
|
+
<path if.bind="icon == 'x-circle'" fill-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25Zm-1.72 6.97a.75.75 0 1 0-1.06 1.06L10.94 12l-1.72 1.72a.75.75 0 1 0 1.06 1.06L12 13.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L13.06 12l1.72-1.72a.75.75 0 1 0-1.06-1.06L12 10.94l-1.72-1.72Z" clip-rule="evenodd"/>
|
|
3295
|
+
</svg>
|
|
3296
|
+
</div>
|
|
3297
|
+
<div class="ml-3 flex-1">
|
|
3298
|
+
<p class="text-sm font-medium"
|
|
3299
|
+
if.bind="title"
|
|
3300
|
+
class.bind="'text-'+color+'-700'">
|
|
3301
|
+
\${title}
|
|
3302
|
+
</p>
|
|
3303
|
+
<div class.bind="title?'mt-2':''">
|
|
3304
|
+
<p class="text-sm"
|
|
3305
|
+
class.bind="'text-'+color+'-700'"
|
|
3306
|
+
innerHTML.bind="content">
|
|
3307
|
+
</p>
|
|
3308
|
+
</div>
|
|
3309
|
+
</div>
|
|
3310
|
+
<div class="ml-auto pl-3">
|
|
3311
|
+
<button type="button"
|
|
3312
|
+
type="button"
|
|
3313
|
+
class="inline-flex rounded-md cursor-pointer"
|
|
3314
|
+
class.bind="'bg-'+color+'-50 text-'+color+'-500 hover:bg-'+color+'-100'"
|
|
3315
|
+
click.trigger="onClickRemove($event)"
|
|
3316
|
+
data-toast="close">
|
|
3317
|
+
<span class="sr-only">Fermer</span>
|
|
3318
|
+
<svg class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
|
|
3319
|
+
<path fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/>
|
|
3320
|
+
</svg>
|
|
3321
|
+
</button>
|
|
3322
|
+
</div>
|
|
3323
|
+
</div>
|
|
3324
|
+
</div>
|
|
3325
|
+
</template>`;
|
|
3326
|
+
|
|
3327
|
+
let BleetToast = (() => {
|
|
3328
|
+
let _classDecorators = [customElement({
|
|
3329
|
+
name: 'bleet-toast',
|
|
3330
|
+
template: template$5
|
|
3331
|
+
})];
|
|
3332
|
+
let _classDescriptor;
|
|
3333
|
+
let _classExtraInitializers = [];
|
|
3334
|
+
let _classThis;
|
|
3335
|
+
let _id_decorators;
|
|
3336
|
+
let _id_initializers = [];
|
|
3337
|
+
let _id_extraInitializers = [];
|
|
3338
|
+
let _color_decorators;
|
|
3339
|
+
let _color_initializers = [];
|
|
3340
|
+
let _color_extraInitializers = [];
|
|
3341
|
+
let _icon_decorators;
|
|
3342
|
+
let _icon_initializers = [];
|
|
3343
|
+
let _icon_extraInitializers = [];
|
|
3344
|
+
let _title_decorators;
|
|
3345
|
+
let _title_initializers = [];
|
|
3346
|
+
let _title_extraInitializers = [];
|
|
3347
|
+
let _content_decorators;
|
|
3348
|
+
let _content_initializers = [];
|
|
3349
|
+
let _content_extraInitializers = [];
|
|
3350
|
+
let _duration_decorators;
|
|
3351
|
+
let _duration_initializers = [];
|
|
3352
|
+
let _duration_extraInitializers = [];
|
|
3353
|
+
(class {
|
|
3354
|
+
static { _classThis = this; }
|
|
3355
|
+
static {
|
|
3356
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
3357
|
+
_id_decorators = [bindable()];
|
|
3358
|
+
_color_decorators = [bindable()];
|
|
3359
|
+
_icon_decorators = [bindable()];
|
|
3360
|
+
_title_decorators = [bindable()];
|
|
3361
|
+
_content_decorators = [bindable()];
|
|
3362
|
+
_duration_decorators = [bindable()];
|
|
3363
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
3364
|
+
__esDecorate(null, null, _color_decorators, { kind: "field", name: "color", static: false, private: false, access: { has: obj => "color" in obj, get: obj => obj.color, set: (obj, value) => { obj.color = value; } }, metadata: _metadata }, _color_initializers, _color_extraInitializers);
|
|
3365
|
+
__esDecorate(null, null, _icon_decorators, { kind: "field", name: "icon", static: false, private: false, access: { has: obj => "icon" in obj, get: obj => obj.icon, set: (obj, value) => { obj.icon = value; } }, metadata: _metadata }, _icon_initializers, _icon_extraInitializers);
|
|
3366
|
+
__esDecorate(null, null, _title_decorators, { kind: "field", name: "title", static: false, private: false, access: { has: obj => "title" in obj, get: obj => obj.title, set: (obj, value) => { obj.title = value; } }, metadata: _metadata }, _title_initializers, _title_extraInitializers);
|
|
3367
|
+
__esDecorate(null, null, _content_decorators, { kind: "field", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content, set: (obj, value) => { obj.content = value; } }, metadata: _metadata }, _content_initializers, _content_extraInitializers);
|
|
3368
|
+
__esDecorate(null, null, _duration_decorators, { kind: "field", name: "duration", static: false, private: false, access: { has: obj => "duration" in obj, get: obj => obj.duration, set: (obj, value) => { obj.duration = value; } }, metadata: _metadata }, _duration_initializers, _duration_extraInitializers);
|
|
3369
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
3370
|
+
_classThis = _classDescriptor.value;
|
|
3371
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
3372
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
3373
|
+
}
|
|
3374
|
+
logger;
|
|
3375
|
+
element;
|
|
3376
|
+
ea;
|
|
3377
|
+
platform;
|
|
3378
|
+
transitionService;
|
|
3379
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
3380
|
+
color = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _color_initializers, UiColor.Info));
|
|
3381
|
+
icon = (__runInitializers(this, _color_extraInitializers), __runInitializers(this, _icon_initializers, UiToastIcon.Info));
|
|
3382
|
+
title = (__runInitializers(this, _icon_extraInitializers), __runInitializers(this, _title_initializers, ''));
|
|
3383
|
+
content = (__runInitializers(this, _title_extraInitializers), __runInitializers(this, _content_initializers, ''));
|
|
3384
|
+
duration = (__runInitializers(this, _content_extraInitializers), __runInitializers(this, _duration_initializers, 0)); // Duration in milliseconds
|
|
3385
|
+
added = (__runInitializers(this, _duration_extraInitializers), false);
|
|
3386
|
+
closeTimeout;
|
|
3387
|
+
// Classes Tailwind complètes pour éviter le purge
|
|
3388
|
+
colorClasses = {
|
|
3389
|
+
[UiColor.Primary]: {
|
|
3390
|
+
container: 'border-primary-300 bg-primary-50',
|
|
3391
|
+
icon: 'text-primary-700',
|
|
3392
|
+
title: 'text-primary-700',
|
|
3393
|
+
content: 'text-primary-700',
|
|
3394
|
+
button: 'bg-primary-50 text-primary-500 hover:bg-primary-100'
|
|
3395
|
+
},
|
|
3396
|
+
[UiColor.Secondary]: {
|
|
3397
|
+
container: 'border-secondary-300 bg-secondary-50',
|
|
3398
|
+
icon: 'text-secondary-700',
|
|
3399
|
+
title: 'text-secondary-700',
|
|
3400
|
+
content: 'text-secondary-700',
|
|
3401
|
+
button: 'bg-secondary-50 text-secondary-500 hover:bg-secondary-100'
|
|
3402
|
+
},
|
|
3403
|
+
[UiColor.Success]: {
|
|
3404
|
+
container: 'border-success-300 bg-success-50',
|
|
3405
|
+
icon: 'text-success-700',
|
|
3406
|
+
title: 'text-success-700',
|
|
3407
|
+
content: 'text-success-700',
|
|
3408
|
+
button: 'bg-success-50 text-success-500 hover:bg-success-100'
|
|
3409
|
+
},
|
|
3410
|
+
[UiColor.Danger]: {
|
|
3411
|
+
container: 'border-danger-300 bg-danger-50',
|
|
3412
|
+
icon: 'text-danger-700',
|
|
3413
|
+
title: 'text-danger-700',
|
|
3414
|
+
content: 'text-danger-700',
|
|
3415
|
+
button: 'bg-danger-50 text-danger-500 hover:bg-danger-100'
|
|
3416
|
+
},
|
|
3417
|
+
[UiColor.Warning]: {
|
|
3418
|
+
container: 'border-warning-300 bg-warning-50',
|
|
3419
|
+
icon: 'text-warning-700',
|
|
3420
|
+
title: 'text-warning-700',
|
|
3421
|
+
content: 'text-warning-700',
|
|
3422
|
+
button: 'bg-warning-50 text-warning-500 hover:bg-warning-100'
|
|
3423
|
+
},
|
|
3424
|
+
[UiColor.Info]: {
|
|
3425
|
+
container: 'border-info-300 bg-info-50',
|
|
3426
|
+
icon: 'text-info-700',
|
|
3427
|
+
title: 'text-info-700',
|
|
3428
|
+
content: 'text-info-700',
|
|
3429
|
+
button: 'bg-info-50 text-info-500 hover:bg-info-100'
|
|
3430
|
+
},
|
|
3431
|
+
[UiColor.Accent]: {
|
|
3432
|
+
container: 'border-accent-300 bg-accent-50',
|
|
3433
|
+
icon: 'text-accent-700',
|
|
3434
|
+
title: 'text-accent-700',
|
|
3435
|
+
content: 'text-accent-700',
|
|
3436
|
+
button: 'bg-accent-50 text-accent-500 hover:bg-accent-100'
|
|
3437
|
+
},
|
|
3438
|
+
};
|
|
3439
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-toast>'), element = resolve(INode), ea = resolve(IEventAggregator), platform = resolve(IPlatform), transitionService = resolve(ITransitionService)) {
|
|
3440
|
+
this.logger = logger;
|
|
3441
|
+
this.element = element;
|
|
3442
|
+
this.ea = ea;
|
|
3443
|
+
this.platform = platform;
|
|
3444
|
+
this.transitionService = transitionService;
|
|
3445
|
+
this.logger.trace('constructor');
|
|
3446
|
+
}
|
|
3447
|
+
attaching() {
|
|
3448
|
+
this.logger.trace('attaching');
|
|
3449
|
+
}
|
|
3450
|
+
attached() {
|
|
3451
|
+
this.logger.trace('attached');
|
|
3452
|
+
if (!this.added) {
|
|
3453
|
+
this.added = true;
|
|
3454
|
+
this.logger.debug(`Toast added with ID: ${this.id}`);
|
|
3455
|
+
this.transitionService.run(this.element, (element) => {
|
|
3456
|
+
if (this.duration > 0) {
|
|
3457
|
+
this.closeTimeout = this.platform.setTimeout(() => {
|
|
3458
|
+
this.close();
|
|
3459
|
+
}, this.duration);
|
|
3460
|
+
}
|
|
3461
|
+
element.classList.add('opacity-100', 'translate-x-0');
|
|
3462
|
+
element.classList.remove('opacity-0', 'translate-x-full');
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
detached() {
|
|
3467
|
+
this.logger.trace('detached');
|
|
3468
|
+
}
|
|
3469
|
+
onClickRemove(evt) {
|
|
3470
|
+
evt.preventDefault();
|
|
3471
|
+
this.logger.trace('onClickRemove');
|
|
3472
|
+
this.close();
|
|
3473
|
+
}
|
|
3474
|
+
close() {
|
|
3475
|
+
if (this.closeTimeout) {
|
|
3476
|
+
this.platform.clearTimeout(this.closeTimeout);
|
|
3477
|
+
}
|
|
3478
|
+
this.transitionService.run(this.element, (element) => {
|
|
3479
|
+
element.classList.add('opacity-0', 'translate-x-full');
|
|
3480
|
+
element.classList.remove('opacity-100', 'translate-x-0');
|
|
3481
|
+
}, (element) => {
|
|
3482
|
+
this.ea.publish(Channels.Toaster, {
|
|
3483
|
+
action: ToasterAction.Remove,
|
|
3484
|
+
toast: { id: this.id }
|
|
3485
|
+
});
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3489
|
+
return _classThis;
|
|
3490
|
+
})();
|
|
3491
|
+
|
|
3492
|
+
var template$4 = `<template class="fixed top-4 right-0 z-70 pr-4 flex flex-col gap-4 pointer-events-none">
|
|
3493
|
+
<bleet-toast repeat.for="[id, toast] of toasts"
|
|
3494
|
+
class="w-90 max-w-full translate-x-full opacity-0 transition-all duration-500 ease-in-out pointer-events-auto"
|
|
3495
|
+
id.bind="id"
|
|
3496
|
+
color.bind="toast.color"
|
|
3497
|
+
icon.bind="toast.icon"
|
|
3498
|
+
title.bind="toast.title"
|
|
3499
|
+
content.bind="toast.content"
|
|
3500
|
+
duration.bind="toast.duration"
|
|
3501
|
+
></bleet-toast>
|
|
3502
|
+
</template>`;
|
|
3503
|
+
|
|
3504
|
+
let BleetToaster = (() => {
|
|
3505
|
+
let _classDecorators = [customElement({
|
|
3506
|
+
name: 'bleet-toaster',
|
|
3507
|
+
template: template$4
|
|
3508
|
+
})];
|
|
3509
|
+
let _classDescriptor;
|
|
3510
|
+
let _classExtraInitializers = [];
|
|
3511
|
+
let _classThis;
|
|
3512
|
+
(class {
|
|
3513
|
+
static { _classThis = this; }
|
|
3514
|
+
static {
|
|
3515
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
3516
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
3517
|
+
_classThis = _classDescriptor.value;
|
|
3518
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
3519
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
3520
|
+
}
|
|
3521
|
+
logger;
|
|
3522
|
+
element;
|
|
3523
|
+
ea;
|
|
3524
|
+
disposable;
|
|
3525
|
+
toasts = new Map();
|
|
3526
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-toaster>'), element = resolve(INode), ea = resolve(IEventAggregator)) {
|
|
3527
|
+
this.logger = logger;
|
|
3528
|
+
this.element = element;
|
|
3529
|
+
this.ea = ea;
|
|
3530
|
+
this.logger.trace('constructor');
|
|
3531
|
+
}
|
|
3532
|
+
attaching() {
|
|
3533
|
+
this.logger.trace('attaching');
|
|
3534
|
+
this.disposable = this.ea.subscribe(Channels.Toaster, this.onToasterEvent);
|
|
3535
|
+
}
|
|
3536
|
+
attached() {
|
|
3537
|
+
this.logger.trace('attached');
|
|
3538
|
+
}
|
|
3539
|
+
detached() {
|
|
3540
|
+
this.logger.trace('detached');
|
|
3541
|
+
this.disposable?.dispose();
|
|
3542
|
+
}
|
|
3543
|
+
dispose() {
|
|
3544
|
+
this.logger.trace('dispose');
|
|
3545
|
+
this.disposable?.dispose();
|
|
3546
|
+
}
|
|
3547
|
+
onToasterEvent = (data) => {
|
|
3548
|
+
this.logger.trace('onToasterEvent', data);
|
|
3549
|
+
if (data.action === ToasterAction.Add && data.toast) {
|
|
3550
|
+
const toast = {
|
|
3551
|
+
id: data.toast.id || crypto.randomUUID(),
|
|
3552
|
+
color: data.toast.color || UiColor.Info,
|
|
3553
|
+
icon: data.toast.icon || UiToastIcon.Info,
|
|
3554
|
+
duration: data.toast.duration || 0,
|
|
3555
|
+
title: data.toast.title,
|
|
3556
|
+
content: data.toast.content,
|
|
3557
|
+
};
|
|
3558
|
+
// @ts-ignore
|
|
3559
|
+
if (!this.toasts.has(toast.id)) {
|
|
3560
|
+
// @ts-ignore
|
|
3561
|
+
this.toasts.set(toast.id, toast);
|
|
3562
|
+
this.logger.debug(`Toast added with ID: ${toast.id}`);
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
else if (data.action === ToasterAction.Remove && data.toast?.id) {
|
|
3566
|
+
if (this.toasts.has(data.toast.id)) {
|
|
3567
|
+
this.toasts.delete(data.toast.id);
|
|
3568
|
+
this.logger.debug(`Toast removed with ID: ${data.toast.id}`);
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
// Handle toaster events here
|
|
3572
|
+
};
|
|
3573
|
+
});
|
|
3574
|
+
return _classThis;
|
|
3575
|
+
})();
|
|
3576
|
+
|
|
3577
|
+
let BleetToasterTrigger = (() => {
|
|
3578
|
+
let _classDecorators = [customElement({
|
|
3579
|
+
name: 'bleet-toaster-trigger',
|
|
3580
|
+
template: null
|
|
3581
|
+
})];
|
|
3582
|
+
let _classDescriptor;
|
|
3583
|
+
let _classExtraInitializers = [];
|
|
3584
|
+
let _classThis;
|
|
3585
|
+
let _id_decorators;
|
|
3586
|
+
let _id_initializers = [];
|
|
3587
|
+
let _id_extraInitializers = [];
|
|
3588
|
+
let _color_decorators;
|
|
3589
|
+
let _color_initializers = [];
|
|
3590
|
+
let _color_extraInitializers = [];
|
|
3591
|
+
let _icon_decorators;
|
|
3592
|
+
let _icon_initializers = [];
|
|
3593
|
+
let _icon_extraInitializers = [];
|
|
3594
|
+
let _title_decorators;
|
|
3595
|
+
let _title_initializers = [];
|
|
3596
|
+
let _title_extraInitializers = [];
|
|
3597
|
+
let _content_decorators;
|
|
3598
|
+
let _content_initializers = [];
|
|
3599
|
+
let _content_extraInitializers = [];
|
|
3600
|
+
let _duration_decorators;
|
|
3601
|
+
let _duration_initializers = [];
|
|
3602
|
+
let _duration_extraInitializers = [];
|
|
3603
|
+
(class {
|
|
3604
|
+
static { _classThis = this; }
|
|
3605
|
+
static {
|
|
3606
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
3607
|
+
_id_decorators = [bindable()];
|
|
3608
|
+
_color_decorators = [bindable()];
|
|
3609
|
+
_icon_decorators = [bindable()];
|
|
3610
|
+
_title_decorators = [bindable()];
|
|
3611
|
+
_content_decorators = [bindable()];
|
|
3612
|
+
_duration_decorators = [bindable()];
|
|
3613
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
3614
|
+
__esDecorate(null, null, _color_decorators, { kind: "field", name: "color", static: false, private: false, access: { has: obj => "color" in obj, get: obj => obj.color, set: (obj, value) => { obj.color = value; } }, metadata: _metadata }, _color_initializers, _color_extraInitializers);
|
|
3615
|
+
__esDecorate(null, null, _icon_decorators, { kind: "field", name: "icon", static: false, private: false, access: { has: obj => "icon" in obj, get: obj => obj.icon, set: (obj, value) => { obj.icon = value; } }, metadata: _metadata }, _icon_initializers, _icon_extraInitializers);
|
|
3616
|
+
__esDecorate(null, null, _title_decorators, { kind: "field", name: "title", static: false, private: false, access: { has: obj => "title" in obj, get: obj => obj.title, set: (obj, value) => { obj.title = value; } }, metadata: _metadata }, _title_initializers, _title_extraInitializers);
|
|
3617
|
+
__esDecorate(null, null, _content_decorators, { kind: "field", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content, set: (obj, value) => { obj.content = value; } }, metadata: _metadata }, _content_initializers, _content_extraInitializers);
|
|
3618
|
+
__esDecorate(null, null, _duration_decorators, { kind: "field", name: "duration", static: false, private: false, access: { has: obj => "duration" in obj, get: obj => obj.duration, set: (obj, value) => { obj.duration = value; } }, metadata: _metadata }, _duration_initializers, _duration_extraInitializers);
|
|
3619
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
3620
|
+
_classThis = _classDescriptor.value;
|
|
3621
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
3622
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
3623
|
+
}
|
|
3624
|
+
logger;
|
|
3625
|
+
element;
|
|
3626
|
+
ea;
|
|
3627
|
+
p;
|
|
3628
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
3629
|
+
color = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _color_initializers, UiColor.Info));
|
|
3630
|
+
icon = (__runInitializers(this, _color_extraInitializers), __runInitializers(this, _icon_initializers, UiToastIcon.Info));
|
|
3631
|
+
title = (__runInitializers(this, _icon_extraInitializers), __runInitializers(this, _title_initializers, ''));
|
|
3632
|
+
content = (__runInitializers(this, _title_extraInitializers), __runInitializers(this, _content_initializers, ''));
|
|
3633
|
+
duration = (__runInitializers(this, _content_extraInitializers), __runInitializers(this, _duration_initializers, 0)); // Duration in milliseconds
|
|
3634
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-toaster-trigger>'), element = resolve(INode), ea = resolve(IEventAggregator), p = resolve(IPlatform)) {
|
|
3635
|
+
this.logger = logger;
|
|
3636
|
+
this.element = element;
|
|
3637
|
+
this.ea = ea;
|
|
3638
|
+
this.p = p;
|
|
3639
|
+
this.logger.trace('constructor');
|
|
3640
|
+
}
|
|
3641
|
+
attaching() {
|
|
3642
|
+
this.logger.trace('attaching');
|
|
3643
|
+
}
|
|
3644
|
+
attached() {
|
|
3645
|
+
this.logger.trace('attached');
|
|
3646
|
+
this.logger.debug(`Triggering toast with`, this.p.document.readyState);
|
|
3647
|
+
if (this.p.document.readyState === 'loading') {
|
|
3648
|
+
this.p.document.addEventListener('DOMContentLoaded', () => {
|
|
3649
|
+
this.onAttach();
|
|
3650
|
+
}, { once: true });
|
|
3651
|
+
}
|
|
3652
|
+
else {
|
|
3653
|
+
this.onAttach();
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
detached() {
|
|
3657
|
+
this.logger.trace('detached');
|
|
3658
|
+
}
|
|
3659
|
+
onAttach = (__runInitializers(this, _duration_extraInitializers), () => {
|
|
3660
|
+
this.logger.trace('onAttach');
|
|
3661
|
+
queueTask(() => {
|
|
3662
|
+
this.ea.publish(Channels.Toaster, {
|
|
3663
|
+
action: ToasterAction.Add, toast: {
|
|
3664
|
+
id: this.id,
|
|
3665
|
+
duration: this.duration,
|
|
3666
|
+
color: this.color,
|
|
3667
|
+
icon: this.icon,
|
|
3668
|
+
title: this.title,
|
|
3669
|
+
content: this.content
|
|
3670
|
+
}
|
|
3671
|
+
});
|
|
3672
|
+
});
|
|
3673
|
+
});
|
|
3674
|
+
});
|
|
3675
|
+
return _classThis;
|
|
3676
|
+
})();
|
|
3677
|
+
|
|
3678
|
+
var template$3 = `<template>
|
|
3679
|
+
<dialog ref="dialogElement"
|
|
3680
|
+
class="fixed inset-0 z-50 size-auto max-h-none max-w-none overflow-y-auto transition ease-in-out duration-300 bg-transparent backdrop:bg-transparent opacity-0">
|
|
3681
|
+
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
|
3682
|
+
<div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl sm:my-8 sm:w-full sm:max-w-lg">
|
|
3683
|
+
|
|
3684
|
+
<!-- Loader -->
|
|
3685
|
+
<div if.bind="loading" class="flex items-center justify-center py-12">
|
|
3686
|
+
<svg class="animate-spin size-8 text-primary-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
3687
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
3688
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
3689
|
+
</svg>
|
|
3690
|
+
</div>
|
|
3691
|
+
|
|
3692
|
+
<!-- Contenu -->
|
|
3693
|
+
<template else>
|
|
3694
|
+
<!-- Header -->
|
|
3695
|
+
<au-compose if.bind="headerView" template.bind="headerView"></au-compose>
|
|
3696
|
+
|
|
3697
|
+
<!-- Content -->
|
|
3698
|
+
<au-compose if.bind="contentView" template.bind="contentView"></au-compose>
|
|
3699
|
+
|
|
3700
|
+
<!-- Footer -->
|
|
3701
|
+
<au-compose if.bind="footerView" template.bind="footerView"></au-compose>
|
|
3702
|
+
</template>
|
|
3703
|
+
|
|
3704
|
+
</div>
|
|
3705
|
+
</div>
|
|
3706
|
+
</dialog>
|
|
3707
|
+
</template>`;
|
|
3708
|
+
|
|
3709
|
+
let BleetModal = (() => {
|
|
3710
|
+
let _classDecorators = [customElement({ name: 'bleet-modal', template: template$3 })];
|
|
3711
|
+
let _classDescriptor;
|
|
3712
|
+
let _classExtraInitializers = [];
|
|
3713
|
+
let _classThis;
|
|
3714
|
+
let _id_decorators;
|
|
3715
|
+
let _id_initializers = [];
|
|
3716
|
+
let _id_extraInitializers = [];
|
|
3717
|
+
var BleetModal = class {
|
|
3718
|
+
static { _classThis = this; }
|
|
3719
|
+
static {
|
|
3720
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
3721
|
+
_id_decorators = [bindable];
|
|
3722
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
3723
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
3724
|
+
BleetModal = _classThis = _classDescriptor.value;
|
|
3725
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
3726
|
+
}
|
|
3727
|
+
logger;
|
|
3728
|
+
ea;
|
|
3729
|
+
platform;
|
|
3730
|
+
transitionService;
|
|
3731
|
+
svgService;
|
|
3732
|
+
apiService;
|
|
3733
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
3734
|
+
dialogElement = __runInitializers(this, _id_extraInitializers);
|
|
3735
|
+
disposable;
|
|
3736
|
+
// State
|
|
3737
|
+
loading = false;
|
|
3738
|
+
color = UiColor.Primary;
|
|
3739
|
+
icon = null;
|
|
3740
|
+
headerView = null;
|
|
3741
|
+
contentView = null;
|
|
3742
|
+
footerView = null;
|
|
3743
|
+
// Color classes — no Tailwind interpolation
|
|
3744
|
+
static ICON_BG_CLASSES = {
|
|
3745
|
+
[UiColor.Primary]: 'bg-primary-100',
|
|
3746
|
+
[UiColor.Secondary]: 'bg-secondary-100',
|
|
3747
|
+
[UiColor.Success]: 'bg-success-100',
|
|
3748
|
+
[UiColor.Danger]: 'bg-danger-100',
|
|
3749
|
+
[UiColor.Warning]: 'bg-warning-100',
|
|
3750
|
+
[UiColor.Info]: 'bg-info-100',
|
|
3751
|
+
[UiColor.Accent]: 'bg-accent-100',
|
|
3752
|
+
};
|
|
3753
|
+
static ICON_TEXT_CLASSES = {
|
|
3754
|
+
[UiColor.Primary]: 'text-primary-600',
|
|
3755
|
+
[UiColor.Secondary]: 'text-secondary-600',
|
|
3756
|
+
[UiColor.Success]: 'text-success-600',
|
|
3757
|
+
[UiColor.Danger]: 'text-danger-600',
|
|
3758
|
+
[UiColor.Warning]: 'text-warning-600',
|
|
3759
|
+
[UiColor.Info]: 'text-info-600',
|
|
3760
|
+
[UiColor.Accent]: 'text-accent-600',
|
|
3761
|
+
};
|
|
3762
|
+
static HEADER_BG_CLASSES = {
|
|
3763
|
+
[UiColor.Primary]: 'bg-primary-600',
|
|
3764
|
+
[UiColor.Secondary]: 'bg-secondary-600',
|
|
3765
|
+
[UiColor.Success]: 'bg-success-600',
|
|
3766
|
+
[UiColor.Danger]: 'bg-danger-600',
|
|
3767
|
+
[UiColor.Warning]: 'bg-warning-600',
|
|
3768
|
+
[UiColor.Info]: 'bg-info-600',
|
|
3769
|
+
[UiColor.Accent]: 'bg-accent-600',
|
|
3770
|
+
};
|
|
3771
|
+
static CLOSE_BUTTON_TEXT_CLASSES = {
|
|
3772
|
+
[UiColor.Primary]: 'text-primary-200',
|
|
3773
|
+
[UiColor.Secondary]: 'text-secondary-200',
|
|
3774
|
+
[UiColor.Success]: 'text-success-200',
|
|
3775
|
+
[UiColor.Danger]: 'text-danger-200',
|
|
3776
|
+
[UiColor.Warning]: 'text-warning-200',
|
|
3777
|
+
[UiColor.Info]: 'text-info-200',
|
|
3778
|
+
[UiColor.Accent]: 'text-accent-200',
|
|
3779
|
+
};
|
|
3780
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-modal>'), ea = resolve(IEventAggregator), platform = resolve(IPlatform), transitionService = resolve(ITransitionService), svgService = resolve(ISvgService), apiService = resolve(IApiService)) {
|
|
3781
|
+
this.logger = logger;
|
|
3782
|
+
this.ea = ea;
|
|
3783
|
+
this.platform = platform;
|
|
3784
|
+
this.transitionService = transitionService;
|
|
3785
|
+
this.svgService = svgService;
|
|
3786
|
+
this.apiService = apiService;
|
|
3787
|
+
}
|
|
3788
|
+
// Getters
|
|
3789
|
+
get iconSvg() {
|
|
3790
|
+
if (!this.icon)
|
|
3791
|
+
return null;
|
|
3792
|
+
return this.svgService.get(this.icon);
|
|
3793
|
+
}
|
|
3794
|
+
get iconBgClass() {
|
|
3795
|
+
return BleetModal.ICON_BG_CLASSES[this.color] ?? BleetModal.ICON_BG_CLASSES[UiColor.Primary];
|
|
3796
|
+
}
|
|
3797
|
+
get iconTextClass() {
|
|
3798
|
+
return BleetModal.ICON_TEXT_CLASSES[this.color] ?? BleetModal.ICON_TEXT_CLASSES[UiColor.Primary];
|
|
3799
|
+
}
|
|
3800
|
+
get headerBgClass() {
|
|
3801
|
+
return BleetModal.HEADER_BG_CLASSES[this.color] ?? BleetModal.HEADER_BG_CLASSES[UiColor.Primary];
|
|
3802
|
+
}
|
|
3803
|
+
get closeButtonTextClass() {
|
|
3804
|
+
return BleetModal.CLOSE_BUTTON_TEXT_CLASSES[this.color] ?? BleetModal.CLOSE_BUTTON_TEXT_CLASSES[UiColor.Primary];
|
|
3805
|
+
}
|
|
3806
|
+
// Lifecycle
|
|
3807
|
+
attached() {
|
|
3808
|
+
this.disposable = this.ea.subscribe(Channels.Modal, this.onModalEvent);
|
|
3809
|
+
this.dialogElement.addEventListener('close', this.onCloseEvent);
|
|
3810
|
+
this.dialogElement.addEventListener('cancel', this.onCancelEvent);
|
|
3811
|
+
}
|
|
3812
|
+
detached() {
|
|
3813
|
+
this.dialogElement.removeEventListener('close', this.onCloseEvent);
|
|
3814
|
+
this.dialogElement.removeEventListener('cancel', this.onCancelEvent);
|
|
3815
|
+
this.disposable?.dispose();
|
|
3816
|
+
}
|
|
3817
|
+
bindDialogEvents() {
|
|
3818
|
+
this.dialogElement.addEventListener('submit', this.onFormSubmit);
|
|
3819
|
+
this.dialogElement.addEventListener('click', this.onDialogClick);
|
|
3820
|
+
}
|
|
3821
|
+
unbindDialogEvents() {
|
|
3822
|
+
this.dialogElement.removeEventListener('submit', this.onFormSubmit);
|
|
3823
|
+
this.dialogElement.removeEventListener('click', this.onDialogClick);
|
|
3824
|
+
}
|
|
3825
|
+
// Handlers
|
|
3826
|
+
onModalEvent = (data) => {
|
|
3827
|
+
if (this.id && this.id !== '' && data.id === this.id) {
|
|
3828
|
+
if (data.action === ModalAction.Open && this.dialogElement.open !== true) {
|
|
3829
|
+
if (data.url) {
|
|
3830
|
+
this.loadFromUrl(data.url);
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
else if (data.action === ModalAction.Close && this.dialogElement.open === true) {
|
|
3834
|
+
this.close();
|
|
3835
|
+
}
|
|
3836
|
+
else if (data.action === ModalAction.Toggle) {
|
|
3837
|
+
if (this.dialogElement.open === true) {
|
|
3838
|
+
this.close();
|
|
3839
|
+
}
|
|
3840
|
+
else if (data.url) {
|
|
3841
|
+
this.loadFromUrl(data.url);
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
};
|
|
3846
|
+
onCloseEvent = (event) => {
|
|
3847
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
3848
|
+
};
|
|
3849
|
+
onCancelEvent = (event) => {
|
|
3850
|
+
this.close();
|
|
3851
|
+
};
|
|
3852
|
+
onDialogClick = (event) => {
|
|
3853
|
+
const target = event.target;
|
|
3854
|
+
if (target.closest('[data-modal="close"]')) {
|
|
3855
|
+
event.preventDefault();
|
|
3856
|
+
this.close();
|
|
3857
|
+
}
|
|
3858
|
+
};
|
|
3859
|
+
onFormSubmit = (event) => {
|
|
3860
|
+
const form = event.target.closest('form');
|
|
3861
|
+
if (!form)
|
|
3862
|
+
return;
|
|
3863
|
+
event.preventDefault();
|
|
3864
|
+
const formData = new FormData(form);
|
|
3865
|
+
const method = formData.get('_method') || form.getAttribute('method') || 'POST';
|
|
3866
|
+
this.apiService
|
|
3867
|
+
.url(form.action)
|
|
3868
|
+
.fromMultipart(formData)
|
|
3869
|
+
.request(method)
|
|
3870
|
+
.then((response) => {
|
|
3871
|
+
this.applyResponse(response.body);
|
|
3872
|
+
})
|
|
3873
|
+
.catch((error) => {
|
|
3874
|
+
this.logger.error('form submit failed', error);
|
|
3875
|
+
this.ea.publish(Channels.Toaster, {
|
|
3876
|
+
action: ToasterAction.Add,
|
|
3877
|
+
toast: { color: UiColor.Danger, content: 'Erreur lors de l\'envoi' }
|
|
3878
|
+
});
|
|
3879
|
+
});
|
|
3880
|
+
};
|
|
3881
|
+
// AJAX
|
|
3882
|
+
loadFromUrl(url) {
|
|
3883
|
+
this.loading = true;
|
|
3884
|
+
this.open();
|
|
3885
|
+
this.apiService.url(url).get()
|
|
3886
|
+
.then((response) => {
|
|
3887
|
+
this.applyResponse(response.body);
|
|
3888
|
+
})
|
|
3889
|
+
.catch((error) => {
|
|
3890
|
+
this.logger.error('loadFromUrl failed', error);
|
|
3891
|
+
this.close();
|
|
3892
|
+
this.ea.publish(Channels.Toaster, {
|
|
3893
|
+
action: ToasterAction.Add,
|
|
3894
|
+
toast: { color: UiColor.Danger, content: 'Erreur de chargement' }
|
|
3895
|
+
});
|
|
3896
|
+
})
|
|
3897
|
+
.finally(() => {
|
|
3898
|
+
this.loading = false;
|
|
3899
|
+
});
|
|
3900
|
+
}
|
|
3901
|
+
applyResponse(response) {
|
|
3902
|
+
// Style
|
|
3903
|
+
this.color = response.color ?? UiColor.Primary;
|
|
3904
|
+
this.icon = response.icon ?? null;
|
|
3905
|
+
// Content
|
|
3906
|
+
if (response.header)
|
|
3907
|
+
this.headerView = response.header;
|
|
3908
|
+
if (response.content)
|
|
3909
|
+
this.contentView = response.content;
|
|
3910
|
+
if (response.footer)
|
|
3911
|
+
this.footerView = response.footer;
|
|
3912
|
+
// Actions
|
|
3913
|
+
this.executeActions(response);
|
|
3914
|
+
}
|
|
3915
|
+
executeActions(response) {
|
|
3916
|
+
// 1. Primary action
|
|
3917
|
+
if (response.action === DialogAction.Close) {
|
|
3918
|
+
this.close();
|
|
3919
|
+
}
|
|
3920
|
+
// DialogAction.Keep → do nothing, dialog stays open
|
|
3921
|
+
// 2. Secondary actions (combinable)
|
|
3922
|
+
if (response.toast) {
|
|
3923
|
+
this.ea.publish(Channels.Toaster, {
|
|
3924
|
+
action: ToasterAction.Add,
|
|
3925
|
+
toast: response.toast
|
|
3926
|
+
});
|
|
3927
|
+
}
|
|
3928
|
+
if (response.ajaxify) {
|
|
3929
|
+
this.ea.publish(Channels.Ajaxify, response.ajaxify);
|
|
3930
|
+
}
|
|
3931
|
+
else if (response.redirect) {
|
|
3932
|
+
this.platform.window.location.href = response.redirect;
|
|
3933
|
+
}
|
|
3934
|
+
else if (response.refresh) {
|
|
3935
|
+
this.platform.window.location.reload();
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
// Open / Close
|
|
3939
|
+
open() {
|
|
3940
|
+
this.bindDialogEvents();
|
|
3941
|
+
this.transitionService.run(this.dialogElement, (element) => {
|
|
3942
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Open });
|
|
3943
|
+
this.ea.publish(Channels.ModalStatus, { status: ModalStatus.Opening, id: this.id });
|
|
3944
|
+
element.showModal();
|
|
3945
|
+
this.platform.requestAnimationFrame(() => {
|
|
3946
|
+
element.classList.add('opacity-100');
|
|
3947
|
+
element.classList.remove('opacity-0');
|
|
3948
|
+
});
|
|
3949
|
+
}, () => {
|
|
3950
|
+
this.ea.publish(Channels.ModalStatus, { status: ModalStatus.Opened, id: this.id });
|
|
3951
|
+
});
|
|
3952
|
+
}
|
|
3953
|
+
close() {
|
|
3954
|
+
this.transitionService.run(this.dialogElement, (element) => {
|
|
3955
|
+
this.ea.publish(Channels.ModalStatus, { status: ModalStatus.Closing, id: this.id });
|
|
3956
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
3957
|
+
element.classList.add('opacity-0');
|
|
3958
|
+
element.classList.remove('opacity-100');
|
|
3959
|
+
}, (element) => {
|
|
3960
|
+
element.close();
|
|
3961
|
+
this.unbindDialogEvents();
|
|
3962
|
+
// Reset
|
|
3963
|
+
this.headerView = null;
|
|
3964
|
+
this.contentView = null;
|
|
3965
|
+
this.footerView = null;
|
|
3966
|
+
this.icon = null;
|
|
3967
|
+
this.color = UiColor.Primary;
|
|
3968
|
+
this.loading = false;
|
|
3969
|
+
this.ea.publish(Channels.ModalStatus, { status: ModalStatus.Closed, id: this.id });
|
|
3970
|
+
});
|
|
3971
|
+
}
|
|
3972
|
+
static {
|
|
3973
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
3974
|
+
}
|
|
3975
|
+
};
|
|
3976
|
+
return BleetModal = _classThis;
|
|
3977
|
+
})();
|
|
3978
|
+
|
|
3979
|
+
var template$2 = `<template>
|
|
3980
|
+
<dialog ref="dialogElement"
|
|
3981
|
+
class="fixed inset-0 z-50 size-auto max-h-none max-w-none overflow-hidden backdrop:bg-transparent bg-transparent transform translate-x-full transition ease-in-out duration-300">
|
|
3982
|
+
<div class="absolute inset-0 pl-10 sm:pl-16 overflow-hidden">
|
|
3983
|
+
<div class="ml-auto flex flex-col h-full w-full sm:w-2/3 sm:min-w-md transform bg-white shadow-xl">
|
|
3984
|
+
|
|
3985
|
+
<!-- Loader -->
|
|
3986
|
+
<div if.bind="loading" class="flex items-center justify-center h-full">
|
|
3987
|
+
<svg class="animate-spin size-8 text-primary-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
3988
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
3989
|
+
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
3990
|
+
</svg>
|
|
3991
|
+
</div>
|
|
3992
|
+
|
|
3993
|
+
<!-- Contenu -->
|
|
3994
|
+
<template else>
|
|
3995
|
+
<!-- Header (fixed) -->
|
|
3996
|
+
<div class="shrink-0">
|
|
3997
|
+
<au-compose if.bind="headerView" template.bind="headerView"></au-compose>
|
|
3998
|
+
</div>
|
|
3999
|
+
|
|
4000
|
+
<!-- Content (scrollable) -->
|
|
4001
|
+
<div class="flex-1 overflow-y-auto">
|
|
4002
|
+
<au-compose if.bind="contentView" template.bind="contentView"></au-compose>
|
|
4003
|
+
</div>
|
|
4004
|
+
|
|
4005
|
+
<!-- Footer (fixed) -->
|
|
4006
|
+
<div class="shrink-0">
|
|
4007
|
+
<au-compose if.bind="footerView" template.bind="footerView"></au-compose>
|
|
4008
|
+
</div>
|
|
4009
|
+
</template>
|
|
4010
|
+
|
|
4011
|
+
</div>
|
|
4012
|
+
</div>
|
|
4013
|
+
</dialog>
|
|
4014
|
+
</template>`;
|
|
4015
|
+
|
|
4016
|
+
let BleetDrawer = (() => {
|
|
4017
|
+
let _classDecorators = [customElement({ name: 'bleet-drawer', template: template$2 })];
|
|
4018
|
+
let _classDescriptor;
|
|
4019
|
+
let _classExtraInitializers = [];
|
|
4020
|
+
let _classThis;
|
|
4021
|
+
let _id_decorators;
|
|
4022
|
+
let _id_initializers = [];
|
|
4023
|
+
let _id_extraInitializers = [];
|
|
4024
|
+
var BleetDrawer = class {
|
|
4025
|
+
static { _classThis = this; }
|
|
4026
|
+
static {
|
|
4027
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
4028
|
+
_id_decorators = [bindable];
|
|
4029
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
4030
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
4031
|
+
BleetDrawer = _classThis = _classDescriptor.value;
|
|
4032
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
4033
|
+
}
|
|
4034
|
+
logger;
|
|
4035
|
+
ea;
|
|
4036
|
+
platform;
|
|
4037
|
+
transitionService;
|
|
4038
|
+
svgService;
|
|
4039
|
+
apiService;
|
|
4040
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
4041
|
+
dialogElement = __runInitializers(this, _id_extraInitializers);
|
|
4042
|
+
disposable;
|
|
4043
|
+
// State
|
|
4044
|
+
loading = false;
|
|
4045
|
+
color = UiColor.Primary;
|
|
4046
|
+
headerView = null;
|
|
4047
|
+
contentView = null;
|
|
4048
|
+
footerView = null;
|
|
4049
|
+
// Color classes for header
|
|
4050
|
+
static HEADER_BG_CLASSES = {
|
|
4051
|
+
[UiColor.Primary]: 'bg-primary-700',
|
|
4052
|
+
[UiColor.Secondary]: 'bg-secondary-700',
|
|
4053
|
+
[UiColor.Success]: 'bg-success-700',
|
|
4054
|
+
[UiColor.Danger]: 'bg-danger-700',
|
|
4055
|
+
[UiColor.Warning]: 'bg-warning-700',
|
|
4056
|
+
[UiColor.Info]: 'bg-info-700',
|
|
4057
|
+
[UiColor.Accent]: 'bg-accent-700',
|
|
4058
|
+
};
|
|
4059
|
+
static CLOSE_BUTTON_TEXT_CLASSES = {
|
|
4060
|
+
[UiColor.Primary]: 'text-primary-200',
|
|
4061
|
+
[UiColor.Secondary]: 'text-secondary-200',
|
|
4062
|
+
[UiColor.Success]: 'text-success-200',
|
|
4063
|
+
[UiColor.Danger]: 'text-danger-200',
|
|
4064
|
+
[UiColor.Warning]: 'text-warning-200',
|
|
4065
|
+
[UiColor.Info]: 'text-info-200',
|
|
4066
|
+
[UiColor.Accent]: 'text-accent-200',
|
|
4067
|
+
};
|
|
4068
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-drawer>'), ea = resolve(IEventAggregator), platform = resolve(IPlatform), transitionService = resolve(ITransitionService), svgService = resolve(ISvgService), apiService = resolve(IApiService)) {
|
|
4069
|
+
this.logger = logger;
|
|
4070
|
+
this.ea = ea;
|
|
4071
|
+
this.platform = platform;
|
|
4072
|
+
this.transitionService = transitionService;
|
|
4073
|
+
this.svgService = svgService;
|
|
4074
|
+
this.apiService = apiService;
|
|
4075
|
+
}
|
|
4076
|
+
// Getters
|
|
4077
|
+
get headerBgClass() {
|
|
4078
|
+
return BleetDrawer.HEADER_BG_CLASSES[this.color] ?? BleetDrawer.HEADER_BG_CLASSES[UiColor.Primary];
|
|
4079
|
+
}
|
|
4080
|
+
get closeButtonTextClass() {
|
|
4081
|
+
return BleetDrawer.CLOSE_BUTTON_TEXT_CLASSES[this.color] ?? BleetDrawer.CLOSE_BUTTON_TEXT_CLASSES[UiColor.Primary];
|
|
4082
|
+
}
|
|
4083
|
+
// Lifecycle
|
|
4084
|
+
attached() {
|
|
4085
|
+
this.disposable = this.ea.subscribe(Channels.Drawer, this.onDrawerEvent);
|
|
4086
|
+
this.dialogElement.addEventListener('close', this.onCloseEvent);
|
|
4087
|
+
this.dialogElement.addEventListener('cancel', this.onCancelEvent);
|
|
4088
|
+
}
|
|
4089
|
+
detached() {
|
|
4090
|
+
this.dialogElement.removeEventListener('close', this.onCloseEvent);
|
|
4091
|
+
this.dialogElement.removeEventListener('cancel', this.onCancelEvent);
|
|
4092
|
+
this.disposable?.dispose();
|
|
4093
|
+
}
|
|
4094
|
+
bindDialogEvents() {
|
|
4095
|
+
this.dialogElement.addEventListener('submit', this.onFormSubmit);
|
|
4096
|
+
this.dialogElement.addEventListener('click', this.onDialogClick);
|
|
4097
|
+
}
|
|
4098
|
+
unbindDialogEvents() {
|
|
4099
|
+
this.dialogElement.removeEventListener('submit', this.onFormSubmit);
|
|
4100
|
+
this.dialogElement.removeEventListener('click', this.onDialogClick);
|
|
4101
|
+
}
|
|
4102
|
+
// Handlers
|
|
4103
|
+
onDrawerEvent = (data) => {
|
|
4104
|
+
if (this.id && this.id !== '' && data.id === this.id) {
|
|
4105
|
+
if (data.action === DrawerAction.Open && this.dialogElement.open !== true) {
|
|
4106
|
+
if (data.url) {
|
|
4107
|
+
this.loadFromUrl(data.url);
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
else if (data.action === DrawerAction.Close && this.dialogElement.open === true) {
|
|
4111
|
+
this.close();
|
|
4112
|
+
}
|
|
4113
|
+
else if (data.action === DrawerAction.Toggle) {
|
|
4114
|
+
if (this.dialogElement.open === true) {
|
|
4115
|
+
this.close();
|
|
4116
|
+
}
|
|
4117
|
+
else if (data.url) {
|
|
4118
|
+
this.loadFromUrl(data.url);
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
};
|
|
4123
|
+
onCloseEvent = (event) => {
|
|
4124
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
4125
|
+
};
|
|
4126
|
+
onCancelEvent = (event) => {
|
|
4127
|
+
this.close();
|
|
4128
|
+
};
|
|
4129
|
+
onDialogClick = (event) => {
|
|
4130
|
+
const target = event.target;
|
|
4131
|
+
if (target.closest('[data-drawer="close"]')) {
|
|
4132
|
+
event.preventDefault();
|
|
4133
|
+
this.close();
|
|
4134
|
+
}
|
|
4135
|
+
};
|
|
4136
|
+
onFormSubmit = (event) => {
|
|
4137
|
+
const form = event.target.closest('form');
|
|
4138
|
+
if (!form)
|
|
4139
|
+
return;
|
|
4140
|
+
event.preventDefault();
|
|
4141
|
+
const formData = new FormData(form);
|
|
4142
|
+
// Capture submitter button name/value (not included by default in FormData)
|
|
4143
|
+
if (event.submitter instanceof HTMLButtonElement && event.submitter.name) {
|
|
4144
|
+
formData.append(event.submitter.name, event.submitter.value || '');
|
|
4145
|
+
}
|
|
4146
|
+
const method = formData.get('_method') || form.getAttribute('method') || 'POST';
|
|
4147
|
+
this.apiService
|
|
4148
|
+
.url(form.action)
|
|
4149
|
+
.fromMultipart(formData)
|
|
4150
|
+
.request(method)
|
|
4151
|
+
.then((response) => {
|
|
4152
|
+
this.applyResponse(response.body);
|
|
4153
|
+
})
|
|
4154
|
+
.catch((error) => {
|
|
4155
|
+
this.logger.error('form submit failed', error);
|
|
4156
|
+
this.ea.publish(Channels.Toaster, {
|
|
4157
|
+
action: ToasterAction.Add,
|
|
4158
|
+
toast: { color: UiColor.Danger, content: 'Erreur lors de l\'envoi' }
|
|
4159
|
+
});
|
|
4160
|
+
});
|
|
4161
|
+
};
|
|
4162
|
+
loadFromUrl(url) {
|
|
4163
|
+
this.loading = true;
|
|
4164
|
+
this.open();
|
|
4165
|
+
this.apiService.url(url).get()
|
|
4166
|
+
.then((response) => {
|
|
4167
|
+
this.applyResponse(response.body);
|
|
4168
|
+
})
|
|
4169
|
+
.catch((error) => {
|
|
4170
|
+
this.logger.error('loadFromUrl failed', error);
|
|
4171
|
+
this.close();
|
|
4172
|
+
this.ea.publish(Channels.Toaster, {
|
|
4173
|
+
action: ToasterAction.Add,
|
|
4174
|
+
toast: { color: UiColor.Danger, content: 'Erreur de chargement' }
|
|
4175
|
+
});
|
|
4176
|
+
})
|
|
4177
|
+
.finally(() => {
|
|
4178
|
+
this.loading = false;
|
|
4179
|
+
});
|
|
4180
|
+
}
|
|
4181
|
+
applyResponse(response) {
|
|
4182
|
+
this.color = response.color ?? UiColor.Primary;
|
|
4183
|
+
if (response.header)
|
|
4184
|
+
this.headerView = response.header;
|
|
4185
|
+
if (response.content)
|
|
4186
|
+
this.contentView = response.content;
|
|
4187
|
+
if (response.footer)
|
|
4188
|
+
this.footerView = response.footer;
|
|
4189
|
+
this.executeActions(response);
|
|
4190
|
+
}
|
|
4191
|
+
executeActions(response) {
|
|
4192
|
+
// 1. Primary action
|
|
4193
|
+
if (response.action === DialogAction.Close) {
|
|
4194
|
+
this.close();
|
|
4195
|
+
}
|
|
4196
|
+
// 2. Secondary actions (combinable)
|
|
4197
|
+
if (response.toast) {
|
|
4198
|
+
this.ea.publish(Channels.Toaster, {
|
|
4199
|
+
action: ToasterAction.Add,
|
|
4200
|
+
toast: response.toast
|
|
4201
|
+
});
|
|
4202
|
+
}
|
|
4203
|
+
if (response.ajaxify) {
|
|
4204
|
+
this.ea.publish(Channels.Ajaxify, response.ajaxify);
|
|
4205
|
+
}
|
|
4206
|
+
else if (response.redirect) {
|
|
4207
|
+
this.platform.window.location.href = response.redirect;
|
|
4208
|
+
}
|
|
4209
|
+
else if (response.refresh) {
|
|
4210
|
+
this.platform.window.location.reload();
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
// Open / Close — translate-x
|
|
4214
|
+
open() {
|
|
4215
|
+
this.bindDialogEvents();
|
|
4216
|
+
this.transitionService.run(this.dialogElement, (element) => {
|
|
4217
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Open });
|
|
4218
|
+
this.ea.publish(Channels.DrawerStatus, { status: DrawerStatus.Opening, id: this.id });
|
|
4219
|
+
element.showModal();
|
|
4220
|
+
this.platform.requestAnimationFrame(() => {
|
|
4221
|
+
element.classList.add('translate-x-0');
|
|
4222
|
+
element.classList.remove('translate-x-full');
|
|
4223
|
+
});
|
|
4224
|
+
}, () => {
|
|
4225
|
+
this.ea.publish(Channels.DrawerStatus, { status: DrawerStatus.Opened, id: this.id });
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
close() {
|
|
4229
|
+
this.transitionService.run(this.dialogElement, (element) => {
|
|
4230
|
+
this.ea.publish(Channels.DrawerStatus, { status: DrawerStatus.Closing, id: this.id });
|
|
4231
|
+
this.ea.publish(Channels.Overlay, { action: OverlayAction.Close });
|
|
4232
|
+
element.classList.add('translate-x-full');
|
|
4233
|
+
element.classList.remove('translate-x-0');
|
|
4234
|
+
}, (element) => {
|
|
4235
|
+
element.close();
|
|
4236
|
+
this.unbindDialogEvents();
|
|
4237
|
+
this.headerView = null;
|
|
4238
|
+
this.contentView = null;
|
|
4239
|
+
this.footerView = null;
|
|
4240
|
+
this.color = UiColor.Primary;
|
|
4241
|
+
this.loading = false;
|
|
4242
|
+
this.ea.publish(Channels.DrawerStatus, { status: DrawerStatus.Closed, id: this.id });
|
|
4243
|
+
});
|
|
4244
|
+
}
|
|
4245
|
+
static {
|
|
4246
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
4247
|
+
}
|
|
4248
|
+
};
|
|
4249
|
+
return BleetDrawer = _classThis;
|
|
4250
|
+
})();
|
|
4251
|
+
|
|
4252
|
+
var template$1 = `<template>
|
|
4253
|
+
<au-slot if.bind="!ajaxedView"></au-slot>
|
|
4254
|
+
<au-compose if.bind="ajaxedView" template.bind="ajaxedView"></au-compose>
|
|
4255
|
+
</template>`;
|
|
4256
|
+
|
|
4257
|
+
class AjaxifyCodec {
|
|
4258
|
+
static codec = {
|
|
4259
|
+
encode: (ctx) => {
|
|
4260
|
+
return Promise.resolve({
|
|
4261
|
+
...ctx,
|
|
4262
|
+
headers: {
|
|
4263
|
+
...ctx.headers,
|
|
4264
|
+
'X-Requested-For': 'Ajaxify',
|
|
4265
|
+
}
|
|
4266
|
+
});
|
|
4267
|
+
}
|
|
4268
|
+
};
|
|
4269
|
+
}
|
|
4270
|
+
|
|
4271
|
+
let BleetAjaxify = (() => {
|
|
4272
|
+
let _classDecorators = [customElement({ name: 'bleet-ajaxify', template: template$1 })];
|
|
4273
|
+
let _classDescriptor;
|
|
4274
|
+
let _classExtraInitializers = [];
|
|
4275
|
+
let _classThis;
|
|
4276
|
+
let _id_decorators;
|
|
4277
|
+
let _id_initializers = [];
|
|
4278
|
+
let _id_extraInitializers = [];
|
|
4279
|
+
let _url_decorators;
|
|
4280
|
+
let _url_initializers = [];
|
|
4281
|
+
let _url_extraInitializers = [];
|
|
4282
|
+
(class {
|
|
4283
|
+
static { _classThis = this; }
|
|
4284
|
+
static {
|
|
4285
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
4286
|
+
_id_decorators = [bindable()];
|
|
4287
|
+
_url_decorators = [bindable()];
|
|
4288
|
+
__esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
|
|
4289
|
+
__esDecorate(null, null, _url_decorators, { kind: "field", name: "url", static: false, private: false, access: { has: obj => "url" in obj, get: obj => obj.url, set: (obj, value) => { obj.url = value; } }, metadata: _metadata }, _url_initializers, _url_extraInitializers);
|
|
4290
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
4291
|
+
_classThis = _classDescriptor.value;
|
|
4292
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
4293
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
4294
|
+
}
|
|
4295
|
+
ea;
|
|
4296
|
+
logger;
|
|
4297
|
+
apiService;
|
|
4298
|
+
id = __runInitializers(this, _id_initializers, '');
|
|
4299
|
+
url = (__runInitializers(this, _id_extraInitializers), __runInitializers(this, _url_initializers, void 0));
|
|
4300
|
+
ajaxedView = (__runInitializers(this, _url_extraInitializers), null);
|
|
4301
|
+
disposable;
|
|
4302
|
+
constructor(ea = resolve(IEventAggregator), logger = resolve(ILogger).scopeTo('<bleet-ajaxify>'), apiService = resolve(IApiService)) {
|
|
4303
|
+
this.ea = ea;
|
|
4304
|
+
this.logger = logger;
|
|
4305
|
+
this.apiService = apiService;
|
|
4306
|
+
this.logger.trace('constructor');
|
|
4307
|
+
}
|
|
4308
|
+
attaching() {
|
|
4309
|
+
this.logger.trace('attaching');
|
|
4310
|
+
this.disposable = this.ea.subscribe(Channels.Ajaxify, this.onEvent);
|
|
4311
|
+
}
|
|
4312
|
+
detaching() {
|
|
4313
|
+
this.logger.trace('detaching');
|
|
4314
|
+
this.disposable?.dispose();
|
|
4315
|
+
}
|
|
4316
|
+
dispose() {
|
|
4317
|
+
this.logger.trace('dispose');
|
|
4318
|
+
this.disposable?.dispose();
|
|
4319
|
+
}
|
|
4320
|
+
onEvent = (data) => {
|
|
4321
|
+
this.logger.trace('onEvent', data);
|
|
4322
|
+
if (data.action === AjaxifyAction.Refresh) {
|
|
4323
|
+
if (data.id && data.id == this.id) {
|
|
4324
|
+
this.logger.debug(`Refreshing ajaxify id=${this.id} from url=${this.url}`);
|
|
4325
|
+
const url = data.url ? data.url : this.url;
|
|
4326
|
+
if (url.length > 1) {
|
|
4327
|
+
this.apiService
|
|
4328
|
+
.url(url)
|
|
4329
|
+
.withInputCodec(AjaxifyCodec.codec)
|
|
4330
|
+
.toText()
|
|
4331
|
+
.get()
|
|
4332
|
+
.then((response) => {
|
|
4333
|
+
this.logger.debug(`Received for id=${this.id}`);
|
|
4334
|
+
this.ajaxedView = response.body;
|
|
4335
|
+
})
|
|
4336
|
+
.catch((error) => {
|
|
4337
|
+
this.logger.error(`Error for id=${this.id}: `, error);
|
|
4338
|
+
});
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
};
|
|
4343
|
+
});
|
|
4344
|
+
return _classThis;
|
|
4345
|
+
})();
|
|
4346
|
+
|
|
4347
|
+
var template = `<template>
|
|
4348
|
+
<input type="hidden" ref="hiddenField">
|
|
4349
|
+
<div ref="editorElement"></div>
|
|
4350
|
+
</template>`;
|
|
4351
|
+
|
|
4352
|
+
const Link = Quill.import('formats/link');
|
|
4353
|
+
class BlackcubeLink extends Link {
|
|
4354
|
+
static create(value) {
|
|
4355
|
+
let node = super.create(value);
|
|
4356
|
+
value = this.sanitize(value);
|
|
4357
|
+
node.setAttribute('href', value);
|
|
4358
|
+
if (value.startsWith("https://") || value.startsWith("http://") || value.startsWith("://")) ;
|
|
4359
|
+
else {
|
|
4360
|
+
node.removeAttribute('target');
|
|
4361
|
+
}
|
|
4362
|
+
return node;
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
Quill.register(BlackcubeLink, true);
|
|
4366
|
+
let Quilljs = (() => {
|
|
4367
|
+
let _classDecorators = [customElement({ name: 'bleet-quilljs', template })];
|
|
4368
|
+
let _classDescriptor;
|
|
4369
|
+
let _classExtraInitializers = [];
|
|
4370
|
+
let _classThis;
|
|
4371
|
+
let _fieldId_decorators;
|
|
4372
|
+
let _fieldId_initializers = [];
|
|
4373
|
+
let _fieldId_extraInitializers = [];
|
|
4374
|
+
let _fieldName_decorators;
|
|
4375
|
+
let _fieldName_initializers = [];
|
|
4376
|
+
let _fieldName_extraInitializers = [];
|
|
4377
|
+
let _content_decorators;
|
|
4378
|
+
let _content_initializers = [];
|
|
4379
|
+
let _content_extraInitializers = [];
|
|
4380
|
+
let _options_decorators;
|
|
4381
|
+
let _options_initializers = [];
|
|
4382
|
+
let _options_extraInitializers = [];
|
|
4383
|
+
(class {
|
|
4384
|
+
static { _classThis = this; }
|
|
4385
|
+
static {
|
|
4386
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
4387
|
+
_fieldId_decorators = [bindable()];
|
|
4388
|
+
_fieldName_decorators = [bindable()];
|
|
4389
|
+
_content_decorators = [bindable()];
|
|
4390
|
+
_options_decorators = [bindable()];
|
|
4391
|
+
__esDecorate(null, null, _fieldId_decorators, { kind: "field", name: "fieldId", static: false, private: false, access: { has: obj => "fieldId" in obj, get: obj => obj.fieldId, set: (obj, value) => { obj.fieldId = value; } }, metadata: _metadata }, _fieldId_initializers, _fieldId_extraInitializers);
|
|
4392
|
+
__esDecorate(null, null, _fieldName_decorators, { kind: "field", name: "fieldName", static: false, private: false, access: { has: obj => "fieldName" in obj, get: obj => obj.fieldName, set: (obj, value) => { obj.fieldName = value; } }, metadata: _metadata }, _fieldName_initializers, _fieldName_extraInitializers);
|
|
4393
|
+
__esDecorate(null, null, _content_decorators, { kind: "field", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content, set: (obj, value) => { obj.content = value; } }, metadata: _metadata }, _content_initializers, _content_extraInitializers);
|
|
4394
|
+
__esDecorate(null, null, _options_decorators, { kind: "field", name: "options", static: false, private: false, access: { has: obj => "options" in obj, get: obj => obj.options, set: (obj, value) => { obj.options = value; } }, metadata: _metadata }, _options_initializers, _options_extraInitializers);
|
|
4395
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
4396
|
+
_classThis = _classDescriptor.value;
|
|
4397
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
4398
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
4399
|
+
}
|
|
4400
|
+
logger;
|
|
4401
|
+
platform;
|
|
4402
|
+
element;
|
|
4403
|
+
hiddenField;
|
|
4404
|
+
editorElement;
|
|
4405
|
+
quill;
|
|
4406
|
+
fieldId = __runInitializers(this, _fieldId_initializers, '');
|
|
4407
|
+
fieldName = (__runInitializers(this, _fieldId_extraInitializers), __runInitializers(this, _fieldName_initializers, ''));
|
|
4408
|
+
content = (__runInitializers(this, _fieldName_extraInitializers), __runInitializers(this, _content_initializers, ''));
|
|
4409
|
+
options = (__runInitializers(this, _content_extraInitializers), __runInitializers(this, _options_initializers, {
|
|
4410
|
+
theme: 'snow',
|
|
4411
|
+
modules: {
|
|
4412
|
+
toolbar: [
|
|
4413
|
+
['bold', 'italic', 'underline'],
|
|
4414
|
+
[{ 'list': 'bullet' }],
|
|
4415
|
+
['link']
|
|
4416
|
+
]
|
|
4417
|
+
},
|
|
4418
|
+
formats: ['bold', 'italic', 'link', 'underline', 'list']
|
|
4419
|
+
}));
|
|
4420
|
+
constructor(logger = resolve(ILogger).scopeTo('<bleet-quilljs>'), platform = resolve(IPlatform), element = resolve(INode)) {
|
|
4421
|
+
this.logger = logger;
|
|
4422
|
+
this.platform = platform;
|
|
4423
|
+
this.element = element;
|
|
4424
|
+
}
|
|
4425
|
+
attached() {
|
|
4426
|
+
this.logger.debug('Attached');
|
|
4427
|
+
if (this.fieldId) {
|
|
4428
|
+
this.hiddenField.id = this.fieldId;
|
|
4429
|
+
}
|
|
4430
|
+
if (this.fieldName) {
|
|
4431
|
+
this.hiddenField.name = this.fieldName;
|
|
4432
|
+
}
|
|
4433
|
+
this.hiddenField.value = this.content;
|
|
4434
|
+
this.editorElement.innerHTML = this.content;
|
|
4435
|
+
this.options.theme = 'snow';
|
|
4436
|
+
this.quill = new Quill(this.editorElement, this.options);
|
|
4437
|
+
this.quill.on('text-change', this.onTextChange);
|
|
4438
|
+
}
|
|
4439
|
+
onTextChange = (__runInitializers(this, _options_extraInitializers), () => {
|
|
4440
|
+
this.hiddenField.value = this.editorElement.querySelector('.ql-editor')?.innerHTML ?? '';
|
|
4441
|
+
this.logger.trace(this.hiddenField.value);
|
|
4442
|
+
});
|
|
4443
|
+
detaching() {
|
|
4444
|
+
this.quill.off('text-change', this.onTextChange);
|
|
4445
|
+
this.logger.debug('Detaching');
|
|
4446
|
+
}
|
|
4447
|
+
});
|
|
4448
|
+
return _classThis;
|
|
4449
|
+
})();
|
|
4450
|
+
|
|
4451
|
+
class RequestCodec {
|
|
4452
|
+
static codec = {
|
|
4453
|
+
encode: (ctx) => {
|
|
4454
|
+
return Promise.resolve({
|
|
4455
|
+
...ctx,
|
|
4456
|
+
headers: {
|
|
4457
|
+
...ctx.headers,
|
|
4458
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
4459
|
+
}
|
|
4460
|
+
});
|
|
4461
|
+
}
|
|
4462
|
+
};
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
const DefaultComponents = [
|
|
4466
|
+
// attributes
|
|
4467
|
+
BleetAlertCustomAttribute,
|
|
4468
|
+
BleetBurgerCustomAttribute,
|
|
4469
|
+
BleetDrawerTriggerCustomAttribute,
|
|
4470
|
+
BleetDropdownCustomAttribute,
|
|
4471
|
+
BleetMenuCustomAttribute,
|
|
4472
|
+
BleetModalTriggerCustomAttribute,
|
|
4473
|
+
BleetPagerCustomAttribute,
|
|
4474
|
+
BleetProfileCustomAttribute,
|
|
4475
|
+
BleetPasswordCustomAttribute,
|
|
4476
|
+
BleetSelectCustomAttribute,
|
|
4477
|
+
BleetBadgeCustomAttribute,
|
|
4478
|
+
BleetTabsCustomAttribute,
|
|
4479
|
+
BleetToasterTriggerCustomAttribute,
|
|
4480
|
+
BleetUploadCustomAttribute,
|
|
4481
|
+
BleetAjaxifyTriggerCustomAttribute,
|
|
4482
|
+
// components
|
|
4483
|
+
BleetOverlay,
|
|
4484
|
+
BleetToast,
|
|
4485
|
+
BleetToaster,
|
|
4486
|
+
BleetToasterTrigger,
|
|
4487
|
+
BleetModal,
|
|
4488
|
+
BleetDrawer,
|
|
4489
|
+
BleetAjaxify,
|
|
4490
|
+
Quilljs
|
|
4491
|
+
];
|
|
4492
|
+
function createBleetConfiguration(optionsCallback) {
|
|
4493
|
+
return {
|
|
4494
|
+
register(container) {
|
|
4495
|
+
const configClass = container.get(IBleetConfiguration);
|
|
4496
|
+
configClass.setContainer(container);
|
|
4497
|
+
if (optionsCallback) {
|
|
4498
|
+
const options = configClass.getConfig();
|
|
4499
|
+
optionsCallback(options);
|
|
4500
|
+
}
|
|
4501
|
+
// Enregistrer l'interface HTTP (toujours disponible)
|
|
4502
|
+
configClass.registerTransportInterface(Transport.Http, IHttpService);
|
|
4503
|
+
// Socketio sera résolu à la demande dans getTransport()
|
|
4504
|
+
return container.register(...DefaultComponents);
|
|
4505
|
+
},
|
|
4506
|
+
customize(callback) {
|
|
4507
|
+
return createBleetConfiguration(callback);
|
|
4508
|
+
}
|
|
4509
|
+
};
|
|
4510
|
+
}
|
|
4511
|
+
const BleetConfiguration = createBleetConfiguration();
|
|
4512
|
+
|
|
4513
|
+
export { AjaxifyAction, AjaxifyCodec, BadgeAction, BleetAjaxify, BleetAjaxifyTriggerCustomAttribute, BleetAlertCustomAttribute, BleetBadgeCustomAttribute, BleetBurgerCustomAttribute, BleetConfiguration, BleetDrawer, BleetDrawerTriggerCustomAttribute, BleetDropdownCustomAttribute, BleetMenuCustomAttribute, BleetModal, BleetModalTriggerCustomAttribute, BleetOverlay, BleetPagerCustomAttribute, BleetPasswordCustomAttribute, BleetProfileCustomAttribute, Quilljs as BleetQuilljs, BleetSelectCustomAttribute, BleetTabsCustomAttribute, BleetToast, BleetToaster, BleetToasterTrigger, BleetToasterTriggerCustomAttribute, BleetUploadCustomAttribute, Channels, CsrfCodec, DialogAction, DrawerAction, DrawerStatus, IApiService, IHttpService, ISocketioService, IStorageService, ISvgService, ITransitionService, ITrapFocusService, MenuAction, MenuStatus, ModalAction, ModalStatus, OverlayAction, OverlayStatus, ProfileAction, ProfileStatus, RequestCodec, ToasterAction, ToasterStatus, Transport, UiColor, UiIcon, UiToastIcon };
|
|
4514
|
+
//# sourceMappingURL=index.es.js.map
|