@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,73 @@
1
+ import { IPlatform, ILogger, bindable, customElement, INode, resolve } from "aurelia";
2
+ import Quill, { QuillOptions } from "quill";
3
+ import template from './bleet-quilljs.html';
4
+
5
+ const Link: any = Quill.import('formats/link');
6
+ class BlackcubeLink extends Link {
7
+ static create(value: any) {
8
+ let node = super.create(value);
9
+ value = this.sanitize(value);
10
+ node.setAttribute('href', value);
11
+ if(value.startsWith("https://") || value.startsWith("http://") || value.startsWith("://")) {
12
+ // do nothing
13
+ } else {
14
+ node.removeAttribute('target');
15
+ }
16
+ return node;
17
+ }
18
+ }
19
+ Quill.register(BlackcubeLink, true);
20
+
21
+ @customElement({ name: 'bleet-quilljs', template })
22
+ export class Quilljs {
23
+ private hiddenField!: HTMLInputElement;
24
+ private editorElement!: HTMLElement;
25
+ private quill!: Quill;
26
+
27
+ @bindable() public fieldId: string = '';
28
+ @bindable() public fieldName: string = '';
29
+ @bindable() public content: string = '';
30
+ @bindable() public options: QuillOptions = {
31
+ theme: 'snow',
32
+ modules: {
33
+ toolbar:[
34
+ ['bold', 'italic', 'underline'],
35
+ [{ 'list': 'bullet' }],
36
+ ['link']
37
+ ]
38
+ },
39
+ formats: ['bold', 'italic', 'link', 'underline', 'list']
40
+ };
41
+
42
+ public constructor(
43
+ private readonly logger: ILogger = resolve(ILogger).scopeTo('<bleet-quilljs>'),
44
+ private readonly platform: IPlatform = resolve(IPlatform),
45
+ private readonly element: HTMLElement = resolve(INode) as HTMLElement,
46
+ ) {
47
+ }
48
+
49
+ public attached(): void {
50
+ this.logger.debug('Attached');
51
+ if (this.fieldId) {
52
+ this.hiddenField.id = this.fieldId;
53
+ }
54
+ if (this.fieldName) {
55
+ this.hiddenField.name = this.fieldName;
56
+ }
57
+ this.hiddenField.value = this.content;
58
+ this.editorElement.innerHTML = this.content;
59
+ this.options.theme = 'snow';
60
+ this.quill = new Quill(this.editorElement, this.options);
61
+ this.quill.on('text-change', this.onTextChange);
62
+ }
63
+
64
+ private onTextChange = () => {
65
+ this.hiddenField.value = this.editorElement.querySelector('.ql-editor')?.innerHTML ?? '';
66
+ this.logger.trace(this.hiddenField.value);
67
+ };
68
+
69
+ public detaching(): void {
70
+ this.quill.off('text-change', this.onTextChange);
71
+ this.logger.debug('Detaching');
72
+ }
73
+ }
@@ -0,0 +1,44 @@
1
+ export default `<template>
2
+ <div class="rounded-md border-l-4 p-4 shadow-lg"
3
+ class.bind="'border-'+color+'-300 bg-'+color+'-50'">
4
+ <div class="flex">
5
+ <div class="shrink-0">
6
+ <svg class="size-5"
7
+ class.bind="'text-'+color+'-500'"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
10
+ <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"/>
11
+ <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"/>
12
+ <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"/>
13
+ <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"/>
14
+ </svg>
15
+ </div>
16
+ <div class="ml-3 flex-1">
17
+ <p class="text-sm font-medium"
18
+ if.bind="title"
19
+ class.bind="'text-'+color+'-700'">
20
+ \${title}
21
+ </p>
22
+ <div class.bind="title?'mt-2':''">
23
+ <p class="text-sm"
24
+ class.bind="'text-'+color+'-700'"
25
+ innerHTML.bind="content">
26
+ </p>
27
+ </div>
28
+ </div>
29
+ <div class="ml-auto pl-3">
30
+ <button type="button"
31
+ type="button"
32
+ class="inline-flex rounded-md cursor-pointer"
33
+ class.bind="'bg-'+color+'-50 text-'+color+'-500 hover:bg-'+color+'-100'"
34
+ click.trigger="onClickRemove($event)"
35
+ data-toast="close">
36
+ <span class="sr-only">Fermer</span>
37
+ <svg class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon">
38
+ <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"/>
39
+ </svg>
40
+ </button>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </template>`
@@ -0,0 +1,133 @@
1
+ import {bindable, customElement, IEventAggregator, ILogger, INode, IPlatform, resolve} from "aurelia";
2
+ import {Channels, ToasterAction, UiColor, UiToastIcon} from '../enums/event-aggregator';
3
+ import {IToaster} from '../interfaces/event-aggregator';
4
+ import {ITransitionService} from '../services/transition-service';
5
+ import template from './bleet-toast.html';
6
+
7
+ @customElement({
8
+ name: 'bleet-toast',
9
+ template
10
+ })
11
+ export class BleetToast {
12
+
13
+ @bindable() public id: string = '';
14
+ @bindable() public color: UiColor = UiColor.Info;
15
+ @bindable() public icon: UiToastIcon = UiToastIcon.Info;
16
+ @bindable() public title: string = '';
17
+ @bindable() public content: string = '';
18
+ @bindable() public duration: number = 0; // Duration in milliseconds
19
+ private added = false;
20
+ private closeTimeout?: number;
21
+
22
+ // Classes Tailwind complètes pour éviter le purge
23
+ private readonly colorClasses: Record<string, { container: string; icon: string; title: string; content: string; button: string }> = {
24
+ [UiColor.Primary]: {
25
+ container: 'border-primary-300 bg-primary-50',
26
+ icon: 'text-primary-700',
27
+ title: 'text-primary-700',
28
+ content: 'text-primary-700',
29
+ button: 'bg-primary-50 text-primary-500 hover:bg-primary-100'
30
+ },
31
+ [UiColor.Secondary]: {
32
+ container: 'border-secondary-300 bg-secondary-50',
33
+ icon: 'text-secondary-700',
34
+ title: 'text-secondary-700',
35
+ content: 'text-secondary-700',
36
+ button: 'bg-secondary-50 text-secondary-500 hover:bg-secondary-100'
37
+ },
38
+ [UiColor.Success]: {
39
+ container: 'border-success-300 bg-success-50',
40
+ icon: 'text-success-700',
41
+ title: 'text-success-700',
42
+ content: 'text-success-700',
43
+ button: 'bg-success-50 text-success-500 hover:bg-success-100'
44
+ },
45
+ [UiColor.Danger]: {
46
+ container: 'border-danger-300 bg-danger-50',
47
+ icon: 'text-danger-700',
48
+ title: 'text-danger-700',
49
+ content: 'text-danger-700',
50
+ button: 'bg-danger-50 text-danger-500 hover:bg-danger-100'
51
+ },
52
+ [UiColor.Warning]: {
53
+ container: 'border-warning-300 bg-warning-50',
54
+ icon: 'text-warning-700',
55
+ title: 'text-warning-700',
56
+ content: 'text-warning-700',
57
+ button: 'bg-warning-50 text-warning-500 hover:bg-warning-100'
58
+ },
59
+ [UiColor.Info]: {
60
+ container: 'border-info-300 bg-info-50',
61
+ icon: 'text-info-700',
62
+ title: 'text-info-700',
63
+ content: 'text-info-700',
64
+ button: 'bg-info-50 text-info-500 hover:bg-info-100'
65
+ },
66
+ [UiColor.Accent]: {
67
+ container: 'border-accent-300 bg-accent-50',
68
+ icon: 'text-accent-700',
69
+ title: 'text-accent-700',
70
+ content: 'text-accent-700',
71
+ button: 'bg-accent-50 text-accent-500 hover:bg-accent-100'
72
+ },
73
+ };
74
+
75
+ public constructor(
76
+ private readonly logger: ILogger = resolve(ILogger).scopeTo('<bleet-toast>'),
77
+ private readonly element: HTMLElement = resolve(INode) as HTMLElement,
78
+ private readonly ea: IEventAggregator = resolve(IEventAggregator),
79
+ private readonly platform: IPlatform = resolve(IPlatform),
80
+ private readonly transitionService: ITransitionService = resolve(ITransitionService),
81
+ ) {
82
+ this.logger.trace('constructor')
83
+ }
84
+
85
+ public attaching()
86
+ {
87
+ this.logger.trace('attaching');
88
+ }
89
+
90
+ public attached()
91
+ {
92
+ this.logger.trace('attached');
93
+ if (!this.added) {
94
+ this.added = true;
95
+ this.logger.debug(`Toast added with ID: ${this.id}`);
96
+ this.transitionService.run(this.element, (element: HTMLElement) => {
97
+ if (this.duration > 0) {
98
+ this.closeTimeout = this.platform.setTimeout(() => {
99
+ this.close();
100
+ }, this.duration);
101
+ }
102
+ element.classList.add('opacity-100', 'translate-x-0');
103
+ element.classList.remove('opacity-0', 'translate-x-full');
104
+ });
105
+ }
106
+ }
107
+
108
+ public detached()
109
+ {
110
+ this.logger.trace('detached');
111
+ }
112
+
113
+ private onClickRemove(evt: Event) {
114
+ evt.preventDefault();
115
+ this.logger.trace('onClickRemove');
116
+ this.close();
117
+ }
118
+
119
+ private close() {
120
+ if (this.closeTimeout) {
121
+ this.platform.clearTimeout(this.closeTimeout);
122
+ }
123
+ this.transitionService.run(this.element, (element: HTMLElement) => {
124
+ element.classList.add('opacity-0', 'translate-x-full');
125
+ element.classList.remove('opacity-100', 'translate-x-0');
126
+ }, (element: HTMLElement) => {
127
+ this.ea.publish(Channels.Toaster, <IToaster>{
128
+ action: ToasterAction.Remove,
129
+ toast: { id: this.id }
130
+ });
131
+ });
132
+ }
133
+ }
@@ -0,0 +1,66 @@
1
+ import {bindable, queueTask, customElement, IEventAggregator, ILogger, INode, IPlatform, resolve} from "aurelia";
2
+ import {Channels, ToasterAction, UiColor, UiToastIcon} from '../enums/event-aggregator';
3
+ import {IToaster} from '../interfaces/event-aggregator';
4
+
5
+
6
+ @customElement({
7
+ name: 'bleet-toaster-trigger',
8
+ template: null
9
+ })
10
+ export class BleetToasterTrigger {
11
+
12
+ @bindable() public id: string = '';
13
+ @bindable() public color: UiColor = UiColor.Info;
14
+ @bindable() public icon: UiToastIcon = UiToastIcon.Info;
15
+ @bindable() public title: string = '';
16
+ @bindable() public content: string = '';
17
+ @bindable() public duration: number = 0; // Duration in milliseconds
18
+ public constructor(
19
+ private readonly logger: ILogger = resolve(ILogger).scopeTo('<bleet-toaster-trigger>'),
20
+ private readonly element: HTMLElement = resolve(INode) as HTMLElement,
21
+ private readonly ea: IEventAggregator = resolve(IEventAggregator),
22
+ private readonly p: IPlatform = resolve(IPlatform),
23
+ ) {
24
+ this.logger.trace('constructor')
25
+ }
26
+
27
+ public attaching()
28
+ {
29
+ this.logger.trace('attaching');
30
+ }
31
+
32
+ public attached()
33
+ {
34
+ this.logger.trace('attached');
35
+ this.logger.debug(`Triggering toast with`, this.p.document.readyState);
36
+ if (this.p.document.readyState === 'loading') {
37
+ this.p.document.addEventListener('DOMContentLoaded', () => {
38
+ this.onAttach();
39
+ }, { once: true });
40
+ } else {
41
+ this.onAttach();
42
+ }
43
+ }
44
+
45
+ public detached()
46
+ {
47
+ this.logger.trace('detached');
48
+ }
49
+
50
+ private onAttach = () => {
51
+ this.logger.trace('onAttach');
52
+ queueTask(() => {
53
+ this.ea.publish(Channels.Toaster, <IToaster>{
54
+ action: ToasterAction.Add, toast:
55
+ {
56
+ id: this.id,
57
+ duration: this.duration,
58
+ color: this.color,
59
+ icon: this.icon,
60
+ title: this.title,
61
+ content: this.content
62
+ }
63
+ });
64
+ });
65
+ }
66
+ }
@@ -0,0 +1,11 @@
1
+ export default `<template class="fixed top-4 right-0 z-70 pr-4 flex flex-col gap-4 pointer-events-none">
2
+ <bleet-toast repeat.for="[id, toast] of toasts"
3
+ class="w-90 max-w-full translate-x-full opacity-0 transition-all duration-500 ease-in-out pointer-events-auto"
4
+ id.bind="id"
5
+ color.bind="toast.color"
6
+ icon.bind="toast.icon"
7
+ title.bind="toast.title"
8
+ content.bind="toast.content"
9
+ duration.bind="toast.duration"
10
+ ></bleet-toast>
11
+ </template>`
@@ -0,0 +1,72 @@
1
+ import {customElement, IDisposable, IEventAggregator, ILogger, INode, resolve} from "aurelia";
2
+ import {Channels, ToasterAction, UiColor, UiToastIcon} from '../enums/event-aggregator';
3
+ import {IToast, IToaster} from '../interfaces/event-aggregator';
4
+ import template from './bleet-toaster.html';
5
+
6
+ @customElement({
7
+ name: 'bleet-toaster',
8
+ template
9
+ })
10
+ export class BleetToaster {
11
+
12
+ private disposable?: IDisposable;
13
+ private toasts: Map<string, IToast> = new Map<string, IToast>();
14
+ public constructor(
15
+ private readonly logger: ILogger = resolve(ILogger).scopeTo('<bleet-toaster>'),
16
+ private readonly element: HTMLElement = resolve(INode) as HTMLElement,
17
+ private readonly ea: IEventAggregator = resolve(IEventAggregator),
18
+ ) {
19
+ this.logger.trace('constructor')
20
+ }
21
+
22
+ public attaching()
23
+ {
24
+ this.logger.trace('attaching');
25
+ this.disposable = this.ea.subscribe(Channels.Toaster, this.onToasterEvent);
26
+ }
27
+
28
+ public attached()
29
+ {
30
+ this.logger.trace('attached');
31
+
32
+ }
33
+
34
+ public detached()
35
+ {
36
+ this.logger.trace('detached');
37
+ this.disposable?.dispose();
38
+ }
39
+
40
+ public dispose()
41
+ {
42
+ this.logger.trace('dispose');
43
+ this.disposable?.dispose();
44
+ }
45
+
46
+ private onToasterEvent = (data: IToaster) => {
47
+ this.logger.trace('onToasterEvent', data);
48
+ if (data.action === ToasterAction.Add && data.toast) {
49
+ const toast :IToast = {
50
+ id: data.toast.id || crypto.randomUUID(),
51
+ color: data.toast.color || UiColor.Info,
52
+ icon: data.toast.icon || UiToastIcon.Info,
53
+ duration: data.toast.duration || 0,
54
+ title: data.toast.title,
55
+ content: data.toast.content,
56
+ };
57
+ // @ts-ignore
58
+ if (!this.toasts.has(toast.id)) {
59
+ // @ts-ignore
60
+ this.toasts.set(toast.id, toast);
61
+ this.logger.debug(`Toast added with ID: ${toast.id}`);
62
+ }
63
+ } else if (data.action === ToasterAction.Remove && data.toast?.id) {
64
+ if (this.toasts.has(data.toast.id)) {
65
+ this.toasts.delete(data.toast.id);
66
+ this.logger.debug(`Toast removed with ID: ${data.toast.id}`);
67
+ }
68
+ }
69
+ // Handle toaster events here
70
+ }
71
+
72
+ }
@@ -0,0 +1,8 @@
1
+ export * from './bleet-overlay';
2
+ export * from './bleet-toast';
3
+ export * from './bleet-toaster';
4
+ export * from './bleet-toaster-trigger';
5
+ export * from './bleet-modal';
6
+ export * from './bleet-drawer';
7
+ export * from './bleet-ajaxify';
8
+ export { Quilljs as BleetQuilljs } from './bleet-quilljs';
@@ -0,0 +1,121 @@
1
+ import { DI, IContainer } from "aurelia";
2
+ import { InterfaceSymbol } from "@aurelia/kernel";
3
+ import {Transport, TransportConfig, TransportEntry, TransportWithConfig} from './enums/api';
4
+ import {ITransport} from './interfaces/api';
5
+
6
+ export interface CsrfConfig {
7
+ enabled: boolean;
8
+ metaName: string;
9
+ headerName: string;
10
+ }
11
+
12
+ export interface ConfigInterface {
13
+ transports?: TransportConfig;
14
+ baseUrl?: string;
15
+ csrf?: CsrfConfig;
16
+ }
17
+
18
+ export interface IBleetConfiguration extends Configure {}
19
+ export const IBleetConfiguration = DI.createInterface<IBleetConfiguration>(
20
+ 'IBleetConfiguration',
21
+ x => x.singleton(Configure)
22
+ );
23
+
24
+ export class Configure {
25
+ protected _config: ConfigInterface = {
26
+ transports: Transport.Http,
27
+ csrf: {
28
+ enabled: true,
29
+ metaName: 'csrf',
30
+ headerName: 'X-CSRF-Token',
31
+ }
32
+ };
33
+
34
+ private _container: IContainer | null = null;
35
+ private _transportInterfaces = new Map<Transport, InterfaceSymbol<ITransport>>();
36
+
37
+ setContainer(container: IContainer): void {
38
+ this._container = container;
39
+ }
40
+
41
+ getContainer(): IContainer | null {
42
+ return this._container;
43
+ }
44
+
45
+ registerTransportInterface(type: Transport, iface: InterfaceSymbol<ITransport>): void {
46
+ this._transportInterfaces.set(type, iface);
47
+ }
48
+
49
+ getCsrfConfig(): CsrfConfig {
50
+ return this._config.csrf ?? { enabled: true, metaName: 'csrf', headerName: 'X-CSRF-Token' };
51
+ }
52
+
53
+ getConfig(): ConfigInterface {
54
+ return this._config;
55
+ }
56
+
57
+ get<T = unknown>(key: string): T {
58
+ return this._config[key] as T;
59
+ }
60
+
61
+ set<T>(key: string, val: T): T {
62
+ this._config[key] = val;
63
+ return val;
64
+ }
65
+
66
+ getTransports(): Transport[] {
67
+ const cfg = this._config.transports ?? Transport.Http;
68
+ const entries: TransportEntry[] = Array.isArray(cfg) ? cfg : [cfg];
69
+ return entries.map(entry => this.isTransportWithConfig(entry) ? entry.type : entry);
70
+ }
71
+
72
+ getBaseUrl(transport: Transport): string {
73
+ const cfg = this._config.transports ?? Transport.Http;
74
+ const entries: TransportEntry[] = Array.isArray(cfg) ? cfg : [cfg];
75
+ const entry = entries.find(e =>
76
+ this.isTransportWithConfig(e) ? e.type === transport : e === transport
77
+ );
78
+ if (entry && this.isTransportWithConfig(entry) && entry.baseUrl !== undefined) {
79
+ return entry.baseUrl;
80
+ }
81
+ return this._config.baseUrl ?? '';
82
+ }
83
+
84
+ private isTransportWithConfig(entry: TransportEntry): entry is TransportWithConfig {
85
+ return typeof entry === 'object' && 'type' in entry;
86
+ }
87
+
88
+ getTransport(type: Transport): ITransport | null {
89
+ if (!this._container) {
90
+ return null;
91
+ }
92
+
93
+ // HTTP : déjà enregistré
94
+ const iface = this._transportInterfaces.get(type);
95
+ if (iface) {
96
+ return this._container.get(iface);
97
+ }
98
+
99
+ // Socketio : require() synchrone à la demande
100
+ if (type === Transport.Socketio) {
101
+ try {
102
+ const { ISocketioService } = require('./services/socketio-service');
103
+ this._transportInterfaces.set(type, ISocketioService);
104
+ return this._container.get(ISocketioService);
105
+ } catch (e) {
106
+ throw new Error(
107
+ 'Transport Socketio configuré mais socket.io-client non installé. ' +
108
+ 'Installez-le avec : npm install socket.io-client'
109
+ );
110
+ }
111
+ }
112
+
113
+ return null;
114
+ }
115
+
116
+ getAvailableTransports(): ITransport[] {
117
+ return this.getTransports()
118
+ .map(t => this.getTransport(t))
119
+ .filter((t): t is ITransport => t !== null);
120
+ }
121
+ }
@@ -0,0 +1,12 @@
1
+ export enum Transport {
2
+ Socketio = 'socketio',
3
+ Http = 'http',
4
+ }
5
+
6
+ export interface TransportWithConfig {
7
+ type: Transport;
8
+ baseUrl?: string;
9
+ }
10
+
11
+ export type TransportEntry = Transport | TransportWithConfig;
12
+ export type TransportConfig = TransportEntry | TransportEntry[];
@@ -0,0 +1,131 @@
1
+ export enum Channels {
2
+ Overlay = 'bleet:overlay',
3
+ OverlayStatus = 'bleet:overlay:status',
4
+ Modal = 'bleet:modal',
5
+ ModalStatus = 'bleet:modal:status',
6
+ Drawer = 'bleet:drawer',
7
+ DrawerStatus = 'bleet:drawer:status',
8
+ Toaster = 'bleet:toaster',
9
+ ToasterStatus = 'bleet:toaster:status',
10
+ Menu = 'bleet:menu',
11
+ MenuStatus = 'bleet:menu:status',
12
+ Badge = 'bleet:badge',
13
+ Profile = 'bleet:profile',
14
+ ProfileStatus = 'bleet:profile:status',
15
+ Ajaxify = 'bleet:ajaxify',
16
+ }
17
+ export enum OverlayAction {
18
+ Open = 'open',
19
+ Close = 'close',
20
+ Toggle = 'toggle',
21
+ }
22
+ export enum OverlayStatus {
23
+ Opening = 'opening',
24
+ Closing = 'closing',
25
+ Opened = 'opened',
26
+ Closed = 'closed',
27
+ }
28
+ export enum ProfileAction {
29
+ Open = 'open',
30
+ Close = 'close',
31
+ Toggle = 'toggle',
32
+ }
33
+ export enum ProfileStatus {
34
+ Opening = 'opening',
35
+ Closing = 'closing',
36
+ Opened = 'opened',
37
+ Closed = 'closed',
38
+ }
39
+ export enum ModalAction {
40
+ Open = 'open',
41
+ Close = 'close',
42
+ Toggle = 'toggle',
43
+ }
44
+ export enum ModalStatus {
45
+ Opening = 'opening',
46
+ Closing = 'closing',
47
+ Opened = 'opened',
48
+ Closed = 'closed',
49
+ }
50
+
51
+ export enum DrawerAction {
52
+ Open = 'open',
53
+ Close = 'close',
54
+ Toggle = 'toggle',
55
+ }
56
+ export enum DrawerStatus {
57
+ Opening = 'opening',
58
+ Closing = 'closing',
59
+ Opened = 'opened',
60
+ Closed = 'closed',
61
+ }
62
+
63
+ export enum AjaxifyAction {
64
+ Refresh = 'refresh',
65
+ }
66
+ export enum ToasterAction {
67
+ Add = 'add',
68
+ Remove = 'remove',
69
+ }
70
+ export enum ToasterStatus {
71
+ Added = 'added',
72
+ Removed = 'removed',
73
+ }
74
+
75
+ export enum MenuAction {
76
+ Open = 'open',
77
+ Close = 'close',
78
+ Toggle = 'toggle',
79
+ }
80
+ export enum BadgeAction {
81
+ Remove = 'remove',
82
+ }
83
+ export enum MenuStatus {
84
+ Opening = 'opening',
85
+ Closing = 'closing',
86
+ Opened = 'opened',
87
+ Closed = 'closed',
88
+ }
89
+
90
+ export enum UiColor {
91
+ Primary = 'primary',
92
+ Secondary = 'secondary',
93
+ Success = 'success',
94
+ Danger = 'danger',
95
+ Warning = 'warning',
96
+ Info = 'info',
97
+ Accent = 'accent',
98
+ }
99
+ export enum UiToastIcon {
100
+ Info = 'information-circle',
101
+ Success = 'check-circle',
102
+ Warning = 'exclamation-triangle',
103
+ Danger = 'x-circle',
104
+ }
105
+
106
+ /**
107
+ * Icônes pour toasts et dialogs
108
+ * Double alias : court (Info) et long (InformationCircle) → même valeur
109
+ */
110
+ export enum UiIcon {
111
+ // Alias courts (usage dev)
112
+ Info = 'information-circle',
113
+ Success = 'check-circle',
114
+ Warning = 'exclamation-triangle',
115
+ Danger = 'x-circle',
116
+
117
+ // Alias longs (match heroicon)
118
+ InformationCircle = 'information-circle',
119
+ CheckCircle = 'check-circle',
120
+ ExclamationTriangle = 'exclamation-triangle',
121
+ XCircle = 'x-circle',
122
+ }
123
+
124
+ /**
125
+ * Actions primaires dialog (mutuellement exclusives)
126
+ */
127
+ export enum DialogAction {
128
+ Keep = 'keep',
129
+ Close = 'close',
130
+ RefreshAndClose = 'refreshAndClose',
131
+ }