@doyosi/laraisy 1.0.1 → 1.0.3

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 (51) hide show
  1. package/LICENSE +1 -1
  2. package/package.json +1 -1
  3. package/src/CodeInput.js +48 -48
  4. package/src/DSAlert.js +352 -352
  5. package/src/DSAvatar.js +207 -207
  6. package/src/DSDelete.js +274 -274
  7. package/src/DSForm.js +568 -568
  8. package/src/DSGridOrTable.js +453 -453
  9. package/src/DSLocaleSwitcher.js +239 -239
  10. package/src/DSLogout.js +293 -293
  11. package/src/DSNotifications.js +365 -365
  12. package/src/DSRestore.js +181 -181
  13. package/src/DSSelect.js +1071 -1071
  14. package/src/DSSelectBox.js +563 -563
  15. package/src/DSSimpleSlider.js +517 -517
  16. package/src/DSSvgFetch.js +69 -69
  17. package/src/DSTable/DSTableExport.js +68 -68
  18. package/src/DSTable/DSTableFilter.js +224 -224
  19. package/src/DSTable/DSTablePagination.js +136 -136
  20. package/src/DSTable/DSTableSearch.js +40 -40
  21. package/src/DSTable/DSTableSelection.js +192 -192
  22. package/src/DSTable/DSTableSort.js +58 -58
  23. package/src/DSTable.js +353 -353
  24. package/src/DSTabs.js +488 -488
  25. package/src/DSUpload.js +887 -887
  26. package/dist/CodeInput.d.ts +0 -10
  27. package/dist/DSAlert.d.ts +0 -112
  28. package/dist/DSAvatar.d.ts +0 -45
  29. package/dist/DSDelete.d.ts +0 -61
  30. package/dist/DSForm.d.ts +0 -151
  31. package/dist/DSGridOrTable/DSGOTRenderer.d.ts +0 -60
  32. package/dist/DSGridOrTable/DSGOTViewToggle.d.ts +0 -26
  33. package/dist/DSGridOrTable.d.ts +0 -296
  34. package/dist/DSLocaleSwitcher.d.ts +0 -71
  35. package/dist/DSLogout.d.ts +0 -76
  36. package/dist/DSNotifications.d.ts +0 -54
  37. package/dist/DSRestore.d.ts +0 -56
  38. package/dist/DSSelect.d.ts +0 -221
  39. package/dist/DSSelectBox.d.ts +0 -123
  40. package/dist/DSSimpleSlider.d.ts +0 -136
  41. package/dist/DSSvgFetch.d.ts +0 -17
  42. package/dist/DSTable/DSTableExport.d.ts +0 -11
  43. package/dist/DSTable/DSTableFilter.d.ts +0 -40
  44. package/dist/DSTable/DSTablePagination.d.ts +0 -12
  45. package/dist/DSTable/DSTableSearch.d.ts +0 -8
  46. package/dist/DSTable/DSTableSelection.d.ts +0 -46
  47. package/dist/DSTable/DSTableSort.d.ts +0 -8
  48. package/dist/DSTable.d.ts +0 -116
  49. package/dist/DSTabs.d.ts +0 -156
  50. package/dist/DSUpload.d.ts +0 -220
  51. package/dist/index.d.ts +0 -17
package/src/DSAvatar.js CHANGED
@@ -1,208 +1,208 @@
1
- import { DSAlert } from './DSAlert.js';
2
-
3
- /**
4
- * DSAvatar
5
- *
6
- * Handles avatar file uploads and resets via AJAX.
7
- * - Integrates with DSAlert for notifications.
8
- * - Manages loading states and UI updates.
9
- * - Uses Laravel-style CSRF protection.
10
- */
11
- export class DSAvatar {
12
-
13
-
14
- /**
15
- * @param {string|HTMLElement} selector - The .avatar-uploader wrapper
16
- * @param {Object} config - Configuration overrides
17
- */
18
- constructor(selector, config = {}) {
19
- this.wrapper = typeof selector === 'string' ? document.querySelector(selector) : selector;
20
- if (!this.wrapper) throw new Error('DSAvatar: Wrapper not found.');
21
-
22
- this.cfg = {
23
- headers: {},
24
- ...config
25
- };
26
-
27
- // Cache elements
28
- this.img = this.wrapper.querySelector('[data-ds-avatar-img]');
29
- this.input = this.wrapper.querySelector('[data-ds-avatar-input]');
30
- this.loadingOverlay = this.wrapper.querySelector('[data-ds-avatar-loading]');
31
- this.triggerBtn = this.wrapper.querySelector('[data-ds-avatar-action="trigger-upload"]');
32
- this.removeBtn = this.wrapper.querySelector('[data-ds-avatar-action="trigger-remove"]');
33
-
34
- // Data attributes
35
- this.uploadUrl = this.wrapper.dataset.uploadUrl;
36
- this.removeUrl = this.wrapper.dataset.removeUrl;
37
- this.inputName = this.wrapper.dataset.name;
38
-
39
- // State backup for error reversion
40
- this._backupSrc = this.img ? this.img.src : '';
41
-
42
- this.bind();
43
- this.initTooltips();
44
- }
45
-
46
- initTooltips() {
47
- if (window.tippy) {
48
- if (this.triggerBtn) window.tippy(this.triggerBtn);
49
- if (this.removeBtn) window.tippy(this.removeBtn);
50
- }
51
- }
52
-
53
- bind() {
54
- // Trigger file input click
55
- if (this.triggerBtn) {
56
- this.triggerBtn.addEventListener('click', (e) => {
57
- e.preventDefault();
58
- this.input.click();
59
- });
60
- }
61
-
62
- // Handle file selection
63
- if (this.input) {
64
- this.input.addEventListener('change', (e) => this._handleFileSelect(e));
65
- }
66
-
67
- // Handle remove/reset
68
- if (this.removeBtn) {
69
- this.removeBtn.addEventListener('click', (e) => {
70
- e.preventDefault();
71
- this._handleRemove();
72
- });
73
- }
74
- }
75
-
76
- /**
77
- * Upload Process
78
- */
79
- async _handleFileSelect(e) {
80
- const file = e.target.files[0];
81
- if (!file) return;
82
-
83
- if (!this.uploadUrl) {
84
- console.warn('DSAvatar: No upload URL provided.');
85
- return;
86
- }
87
-
88
- // 1. Show loading
89
- this._toggleLoading(true);
90
-
91
- // 2. Prepare Data
92
- const formData = new FormData();
93
- formData.append(this.inputName, file);
94
- // Append _method if needed, usually POST for upload
95
-
96
- try {
97
- const { response, data } = await this._sendRequest(this.uploadUrl, 'POST', formData);
98
-
99
- if (response.ok) {
100
- // Success: Update Image & Toast
101
- if (data.url) this.img.src = data.url;
102
- this._backupSrc = data.url; // Update backup on success
103
- this.input.value = ''; // Clear input to allow re-uploading same file
104
- this._toast(data.message || 'Avatar updated successfully', 'success');
105
- } else {
106
- // Server Error
107
- throw new Error(data.message || 'Upload failed');
108
- }
109
- } catch (err) {
110
- // Error: Revert & Toast
111
- console.error(err);
112
- this.img.src = this._backupSrc;
113
- this.input.value = '';
114
- this._toast(err.message || 'Network error occurred', 'error');
115
- } finally {
116
- this._toggleLoading(false);
117
- }
118
- }
119
-
120
- /**
121
- * Remove/Reset Process
122
- */
123
- async _handleRemove() {
124
- if (!this.removeUrl) return;
125
-
126
- // Confirm dialog (Optional, but good UX)
127
- /*
128
- const confirmed = confirm('Reset avatar to default?');
129
- if (!confirmed) return;
130
- */
131
-
132
- this._toggleLoading(true);
133
-
134
- try {
135
- // Usually DELETE or POST with _method=DELETE
136
- const formData = new FormData();
137
- formData.append('_method', 'DELETE');
138
-
139
- const { response, data } = await this._sendRequest(this.removeUrl, 'POST', formData);
140
-
141
- if (response.ok) {
142
- if (data.url) this.img.src = data.url; // Server usually returns the default placeholder URL
143
- this._backupSrc = this.img.src;
144
- this._toast(data.message || 'Avatar reset successfully', 'success');
145
- } else {
146
- throw new Error(data.message || 'Reset failed');
147
- }
148
- } catch (err) {
149
- console.error(err);
150
- this._toast(err.message || 'Could not reset avatar', 'error');
151
- } finally {
152
- this._toggleLoading(false);
153
- }
154
- }
155
-
156
- /**
157
- * Shared Request Logic (mirrors DSForm)
158
- */
159
- async _sendRequest(url, method, body) {
160
- const headers = {
161
- 'Accept': 'application/json',
162
- 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
163
- ...this.cfg.headers
164
- };
165
-
166
- const resp = await fetch(url, {
167
- method: method,
168
- headers: headers,
169
- body: body
170
- });
171
-
172
- let data = {};
173
- try {
174
- data = await resp.json();
175
- } catch (e) { /* ignore non-json */ }
176
-
177
- return { response: resp, data };
178
- }
179
-
180
- _toggleLoading(show) {
181
- if (show) {
182
- this.loadingOverlay.classList.remove('hidden');
183
- if (this.triggerBtn) this.triggerBtn.disabled = true;
184
- if (this.removeBtn) this.removeBtn.disabled = true;
185
- } else {
186
- this.loadingOverlay.classList.add('hidden');
187
- if (this.triggerBtn) this.triggerBtn.disabled = false;
188
- if (this.removeBtn) this.removeBtn.disabled = false;
189
- }
190
- }
191
-
192
- _toast(message, type = 'info') {
193
- if (typeof DSAlert !== 'undefined') {
194
- DSAlert.fire({
195
- toast: true,
196
- icon: type,
197
- title: message,
198
- position: 'top-end',
199
- showConfirmButton: false,
200
- timer: 3000,
201
- timerProgressBar: true,
202
- });
203
- } else {
204
- // Fallback if DSAlert is missing
205
- console.log(`[${type.toUpperCase()}] ${message}`);
206
- }
207
- }
1
+ import { DSAlert } from './DSAlert.js';
2
+
3
+ /**
4
+ * DSAvatar
5
+ *
6
+ * Handles avatar file uploads and resets via AJAX.
7
+ * - Integrates with DSAlert for notifications.
8
+ * - Manages loading states and UI updates.
9
+ * - Uses Laravel-style CSRF protection.
10
+ */
11
+ export class DSAvatar {
12
+
13
+
14
+ /**
15
+ * @param {string|HTMLElement} selector - The .avatar-uploader wrapper
16
+ * @param {Object} config - Configuration overrides
17
+ */
18
+ constructor(selector, config = {}) {
19
+ this.wrapper = typeof selector === 'string' ? document.querySelector(selector) : selector;
20
+ if (!this.wrapper) throw new Error('DSAvatar: Wrapper not found.');
21
+
22
+ this.cfg = {
23
+ headers: {},
24
+ ...config
25
+ };
26
+
27
+ // Cache elements
28
+ this.img = this.wrapper.querySelector('[data-ds-avatar-img]');
29
+ this.input = this.wrapper.querySelector('[data-ds-avatar-input]');
30
+ this.loadingOverlay = this.wrapper.querySelector('[data-ds-avatar-loading]');
31
+ this.triggerBtn = this.wrapper.querySelector('[data-ds-avatar-action="trigger-upload"]');
32
+ this.removeBtn = this.wrapper.querySelector('[data-ds-avatar-action="trigger-remove"]');
33
+
34
+ // Data attributes
35
+ this.uploadUrl = this.wrapper.dataset.uploadUrl;
36
+ this.removeUrl = this.wrapper.dataset.removeUrl;
37
+ this.inputName = this.wrapper.dataset.name;
38
+
39
+ // State backup for error reversion
40
+ this._backupSrc = this.img ? this.img.src : '';
41
+
42
+ this.bind();
43
+ this.initTooltips();
44
+ }
45
+
46
+ initTooltips() {
47
+ if (window.tippy) {
48
+ if (this.triggerBtn) window.tippy(this.triggerBtn);
49
+ if (this.removeBtn) window.tippy(this.removeBtn);
50
+ }
51
+ }
52
+
53
+ bind() {
54
+ // Trigger file input click
55
+ if (this.triggerBtn) {
56
+ this.triggerBtn.addEventListener('click', (e) => {
57
+ e.preventDefault();
58
+ this.input.click();
59
+ });
60
+ }
61
+
62
+ // Handle file selection
63
+ if (this.input) {
64
+ this.input.addEventListener('change', (e) => this._handleFileSelect(e));
65
+ }
66
+
67
+ // Handle remove/reset
68
+ if (this.removeBtn) {
69
+ this.removeBtn.addEventListener('click', (e) => {
70
+ e.preventDefault();
71
+ this._handleRemove();
72
+ });
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Upload Process
78
+ */
79
+ async _handleFileSelect(e) {
80
+ const file = e.target.files[0];
81
+ if (!file) return;
82
+
83
+ if (!this.uploadUrl) {
84
+ console.warn('DSAvatar: No upload URL provided.');
85
+ return;
86
+ }
87
+
88
+ // 1. Show loading
89
+ this._toggleLoading(true);
90
+
91
+ // 2. Prepare Data
92
+ const formData = new FormData();
93
+ formData.append(this.inputName, file);
94
+ // Append _method if needed, usually POST for upload
95
+
96
+ try {
97
+ const { response, data } = await this._sendRequest(this.uploadUrl, 'POST', formData);
98
+
99
+ if (response.ok) {
100
+ // Success: Update Image & Toast
101
+ if (data.url) this.img.src = data.url;
102
+ this._backupSrc = data.url; // Update backup on success
103
+ this.input.value = ''; // Clear input to allow re-uploading same file
104
+ this._toast(data.message || 'Avatar updated successfully', 'success');
105
+ } else {
106
+ // Server Error
107
+ throw new Error(data.message || 'Upload failed');
108
+ }
109
+ } catch (err) {
110
+ // Error: Revert & Toast
111
+ console.error(err);
112
+ this.img.src = this._backupSrc;
113
+ this.input.value = '';
114
+ this._toast(err.message || 'Network error occurred', 'error');
115
+ } finally {
116
+ this._toggleLoading(false);
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Remove/Reset Process
122
+ */
123
+ async _handleRemove() {
124
+ if (!this.removeUrl) return;
125
+
126
+ // Confirm dialog (Optional, but good UX)
127
+ /*
128
+ const confirmed = confirm('Reset avatar to default?');
129
+ if (!confirmed) return;
130
+ */
131
+
132
+ this._toggleLoading(true);
133
+
134
+ try {
135
+ // Usually DELETE or POST with _method=DELETE
136
+ const formData = new FormData();
137
+ formData.append('_method', 'DELETE');
138
+
139
+ const { response, data } = await this._sendRequest(this.removeUrl, 'POST', formData);
140
+
141
+ if (response.ok) {
142
+ if (data.url) this.img.src = data.url; // Server usually returns the default placeholder URL
143
+ this._backupSrc = this.img.src;
144
+ this._toast(data.message || 'Avatar reset successfully', 'success');
145
+ } else {
146
+ throw new Error(data.message || 'Reset failed');
147
+ }
148
+ } catch (err) {
149
+ console.error(err);
150
+ this._toast(err.message || 'Could not reset avatar', 'error');
151
+ } finally {
152
+ this._toggleLoading(false);
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Shared Request Logic (mirrors DSForm)
158
+ */
159
+ async _sendRequest(url, method, body) {
160
+ const headers = {
161
+ 'Accept': 'application/json',
162
+ 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
163
+ ...this.cfg.headers
164
+ };
165
+
166
+ const resp = await fetch(url, {
167
+ method: method,
168
+ headers: headers,
169
+ body: body
170
+ });
171
+
172
+ let data = {};
173
+ try {
174
+ data = await resp.json();
175
+ } catch (e) { /* ignore non-json */ }
176
+
177
+ return { response: resp, data };
178
+ }
179
+
180
+ _toggleLoading(show) {
181
+ if (show) {
182
+ this.loadingOverlay.classList.remove('hidden');
183
+ if (this.triggerBtn) this.triggerBtn.disabled = true;
184
+ if (this.removeBtn) this.removeBtn.disabled = true;
185
+ } else {
186
+ this.loadingOverlay.classList.add('hidden');
187
+ if (this.triggerBtn) this.triggerBtn.disabled = false;
188
+ if (this.removeBtn) this.removeBtn.disabled = false;
189
+ }
190
+ }
191
+
192
+ _toast(message, type = 'info') {
193
+ if (typeof DSAlert !== 'undefined') {
194
+ DSAlert.fire({
195
+ toast: true,
196
+ icon: type,
197
+ title: message,
198
+ position: 'top-end',
199
+ showConfirmButton: false,
200
+ timer: 3000,
201
+ timerProgressBar: true,
202
+ });
203
+ } else {
204
+ // Fallback if DSAlert is missing
205
+ console.log(`[${type.toUpperCase()}] ${message}`);
206
+ }
207
+ }
208
208
  }