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