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