@liwe3/webcomponents 1.0.14 → 1.1.10

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 (85) hide show
  1. package/dist/AIMarkdownEditor.d.ts +35 -0
  2. package/dist/AIMarkdownEditor.d.ts.map +1 -0
  3. package/dist/AIMarkdownEditor.js +412 -0
  4. package/dist/AIMarkdownEditor.js.map +1 -0
  5. package/dist/AITextEditor.d.ts +183 -0
  6. package/dist/AITextEditor.d.ts.map +1 -0
  7. package/dist/AITextEditor.js +63 -27
  8. package/dist/AITextEditor.js.map +1 -1
  9. package/dist/ButtonToolbar.d.ts +35 -0
  10. package/dist/ButtonToolbar.d.ts.map +1 -0
  11. package/dist/ButtonToolbar.js +220 -0
  12. package/dist/ButtonToolbar.js.map +1 -0
  13. package/dist/CheckList.d.ts +31 -0
  14. package/dist/CheckList.d.ts.map +1 -0
  15. package/dist/CheckList.js +336 -0
  16. package/dist/CheckList.js.map +1 -0
  17. package/dist/ChunkUploader.d.ts +125 -0
  18. package/dist/ChunkUploader.d.ts.map +1 -0
  19. package/dist/ChunkUploader.js +756 -0
  20. package/dist/ChunkUploader.js.map +1 -0
  21. package/dist/ComicBalloon.d.ts +82 -0
  22. package/dist/ComicBalloon.d.ts.map +1 -0
  23. package/dist/ComicBalloon.js +346 -0
  24. package/dist/ComicBalloon.js.map +1 -0
  25. package/dist/ContainerBox.d.ts +112 -0
  26. package/dist/ContainerBox.d.ts.map +1 -0
  27. package/dist/ContainerBox.js +359 -0
  28. package/dist/ContainerBox.js.map +1 -0
  29. package/dist/DateSelector.d.ts +103 -0
  30. package/dist/DateSelector.d.ts.map +1 -0
  31. package/dist/Dialog.d.ts +102 -0
  32. package/dist/Dialog.d.ts.map +1 -0
  33. package/dist/Dialog.js +299 -0
  34. package/dist/Dialog.js.map +1 -0
  35. package/dist/Drawer.d.ts +63 -0
  36. package/dist/Drawer.d.ts.map +1 -0
  37. package/dist/Drawer.js +340 -0
  38. package/dist/Drawer.js.map +1 -0
  39. package/dist/ImageView.d.ts +42 -0
  40. package/dist/ImageView.d.ts.map +1 -0
  41. package/dist/ImageView.js +209 -0
  42. package/dist/ImageView.js.map +1 -0
  43. package/dist/MarkdownPreview.d.ts +25 -0
  44. package/dist/MarkdownPreview.d.ts.map +1 -0
  45. package/dist/MarkdownPreview.js +147 -0
  46. package/dist/MarkdownPreview.js.map +1 -0
  47. package/dist/PopoverMenu.d.ts +103 -0
  48. package/dist/PopoverMenu.d.ts.map +1 -0
  49. package/dist/ResizableCropper.d.ts +158 -0
  50. package/dist/ResizableCropper.d.ts.map +1 -0
  51. package/dist/ResizableCropper.js +562 -0
  52. package/dist/ResizableCropper.js.map +1 -0
  53. package/dist/SmartSelect.d.ts +100 -0
  54. package/dist/SmartSelect.d.ts.map +1 -0
  55. package/dist/SmartSelect.js +45 -2
  56. package/dist/SmartSelect.js.map +1 -1
  57. package/dist/Toast.d.ts +127 -0
  58. package/dist/Toast.d.ts.map +1 -0
  59. package/dist/Toast.js +79 -49
  60. package/dist/Toast.js.map +1 -1
  61. package/dist/TreeView.d.ts +84 -0
  62. package/dist/TreeView.d.ts.map +1 -0
  63. package/dist/TreeView.js +478 -0
  64. package/dist/TreeView.js.map +1 -0
  65. package/dist/index.d.ts +23 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +51 -14
  68. package/dist/index.js.map +1 -1
  69. package/package.json +60 -5
  70. package/src/AIMarkdownEditor.ts +568 -0
  71. package/src/AITextEditor.ts +97 -2
  72. package/src/ButtonToolbar.ts +302 -0
  73. package/src/CheckList.ts +438 -0
  74. package/src/ChunkUploader.ts +1135 -0
  75. package/src/ComicBalloon.ts +709 -0
  76. package/src/ContainerBox.ts +570 -0
  77. package/src/Dialog.ts +510 -0
  78. package/src/Drawer.ts +435 -0
  79. package/src/ImageView.ts +265 -0
  80. package/src/MarkdownPreview.ts +213 -0
  81. package/src/ResizableCropper.ts +1099 -0
  82. package/src/SmartSelect.ts +48 -2
  83. package/src/Toast.ts +96 -32
  84. package/src/TreeView.ts +673 -0
  85. package/src/index.ts +129 -27
@@ -0,0 +1,570 @@
1
+ /**
2
+ * ContainerBox Web Component
3
+ * A container that wraps elements and shows a menu on hover
4
+ */
5
+
6
+ import type { PopoverMenuItem } from './PopoverMenu';
7
+
8
+ export type MenuPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
9
+
10
+ export type ContainerBoxConfig = {
11
+ menuPosition?: MenuPosition;
12
+ menuItems?: PopoverMenuItem[];
13
+ alwaysShowMenu?: boolean;
14
+ };
15
+
16
+ export class ContainerBoxElement extends HTMLElement {
17
+ declare shadowRoot: ShadowRoot;
18
+ private menuPosition: MenuPosition = 'bottom-left';
19
+ private menuItems: PopoverMenuItem[] = [];
20
+ private alwaysShowMenu: boolean = false;
21
+ private popoverMenu: HTMLElement | null = null;
22
+ private menuButton: HTMLElement | null = null;
23
+
24
+ constructor() {
25
+ super();
26
+ this.attachShadow({ mode: 'open' });
27
+ }
28
+
29
+ connectedCallback(): void {
30
+ this.render();
31
+ this.setupEventListeners();
32
+ }
33
+
34
+ disconnectedCallback(): void {
35
+ this.cleanupEventListeners();
36
+ }
37
+
38
+ /**
39
+ * Set menu position
40
+ */
41
+ setMenuPosition(position: MenuPosition): void {
42
+ this.menuPosition = position;
43
+ this.updateMenuButtonPosition();
44
+ }
45
+
46
+ /**
47
+ * Get menu position
48
+ */
49
+ getMenuPosition(): MenuPosition {
50
+ return this.menuPosition;
51
+ }
52
+
53
+ /**
54
+ * Set menu items
55
+ */
56
+ setMenuItems(items: PopoverMenuItem[]): void {
57
+ this.menuItems = items;
58
+ this.updatePopoverMenu();
59
+ }
60
+
61
+ /**
62
+ * Get menu items
63
+ */
64
+ getMenuItems(): PopoverMenuItem[] {
65
+ return this.menuItems;
66
+ }
67
+
68
+ /**
69
+ * Set whether menu button is always visible
70
+ */
71
+ setAlwaysShowMenu(value: boolean): void {
72
+ this.alwaysShowMenu = value;
73
+ this.updateMenuButtonVisibility();
74
+ }
75
+
76
+ /**
77
+ * Get whether menu button is always visible
78
+ */
79
+ getAlwaysShowMenu(): boolean {
80
+ return this.alwaysShowMenu;
81
+ }
82
+
83
+ /**
84
+ * Render the component
85
+ */
86
+ private render(): void {
87
+ this.shadowRoot.innerHTML = `
88
+ <style>
89
+ :host {
90
+ display: block;
91
+ position: relative;
92
+ font-family: var(--font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
93
+ }
94
+
95
+ .container-box {
96
+ position: relative;
97
+ width: 100%;
98
+ height: 100%;
99
+ }
100
+
101
+ .content-wrapper {
102
+ width: 100%;
103
+ height: 100%;
104
+ }
105
+
106
+ .menu-button {
107
+ position: absolute;
108
+ background: var(--container-box-menu-bg, #fff);
109
+ border: 1px solid var(--container-box-menu-border, #ddd);
110
+ border-radius: var(--container-box-menu-radius, 4px);
111
+ padding: var(--container-box-menu-padding, 6px 10px);
112
+ cursor: pointer;
113
+ box-shadow: var(--container-box-menu-shadow, 0 2px 8px rgba(0,0,0,0.15));
114
+ z-index: 10;
115
+ opacity: 0;
116
+ transition: opacity 0.2s;
117
+ display: flex;
118
+ align-items: center;
119
+ gap: 4px;
120
+ font-size: 14px;
121
+ color: var(--container-box-menu-color, #333);
122
+ }
123
+
124
+ .menu-button:hover {
125
+ background: var(--container-box-menu-hover-bg, #f5f5f5);
126
+ }
127
+
128
+ .container-box:hover .menu-button {
129
+ opacity: 1;
130
+ }
131
+
132
+ .menu-button.always-visible {
133
+ opacity: 1;
134
+ }
135
+
136
+ .menu-button-icon {
137
+ width: 16px;
138
+ height: 16px;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ }
143
+
144
+ /* Position variants */
145
+ .menu-button.top-left {
146
+ top: var(--container-box-menu-offset, 8px);
147
+ left: var(--container-box-menu-offset, 8px);
148
+ }
149
+
150
+ .menu-button.top-right {
151
+ top: var(--container-box-menu-offset, 8px);
152
+ right: var(--container-box-menu-offset, 8px);
153
+ }
154
+
155
+ .menu-button.bottom-left {
156
+ bottom: var(--container-box-menu-offset, 8px);
157
+ left: var(--container-box-menu-offset, 8px);
158
+ }
159
+
160
+ .menu-button.bottom-right {
161
+ bottom: var(--container-box-menu-offset, 8px);
162
+ right: var(--container-box-menu-offset, 8px);
163
+ }
164
+
165
+ .popover-container {
166
+ position: fixed;
167
+ z-index: 10000;
168
+ pointer-events: none;
169
+ }
170
+
171
+ .popover-container > * {
172
+ pointer-events: auto;
173
+ }
174
+ </style>
175
+
176
+ <div class="container-box">
177
+ <div class="content-wrapper">
178
+ <slot></slot>
179
+ </div>
180
+ <div class="menu-button ${this.menuPosition} ${this.alwaysShowMenu ? 'always-visible' : ''}">
181
+ <span class="menu-button-icon">⋮</span>
182
+ </div>
183
+ </div>
184
+ <div class="popover-container"></div>
185
+ `;
186
+
187
+ this.menuButton = this.shadowRoot.querySelector('.menu-button');
188
+ this.createPopoverMenu();
189
+ }
190
+
191
+ /**
192
+ * Create the popover menu
193
+ */
194
+ private createPopoverMenu(): void {
195
+ // We'll create the popover dynamically when needed
196
+ }
197
+
198
+ /**
199
+ * Update popover menu items
200
+ */
201
+ private updatePopoverMenu(): void {
202
+ // Menu items are stored and used when showing the menu
203
+ }
204
+
205
+ /**
206
+ * Render menu items recursively
207
+ */
208
+ private renderMenuItems(items: PopoverMenuItem[]): string {
209
+ return items.map(item => {
210
+ if (item.label === '---sep') {
211
+ return '<div class="menu-separator"></div>';
212
+ }
213
+
214
+ const hasSubmenu = item.items && item.items.length > 0;
215
+ const isDisabled = item.enabled === false;
216
+ const disabledClass = isDisabled ? 'disabled' : '';
217
+ const submenuClass = hasSubmenu ? 'has-submenu' : '';
218
+
219
+ return `
220
+ <div class="menu-item ${disabledClass} ${submenuClass}" data-has-submenu="${hasSubmenu}">
221
+ <span class="menu-item-label">${item.label}</span>
222
+ ${hasSubmenu ? '<span class="menu-item-arrow">▶</span>' : ''}
223
+ ${hasSubmenu ? `<div class="submenu">${this.renderMenuItems(item.items!)}</div>` : ''}
224
+ </div>
225
+ `;
226
+ }).join('');
227
+ }
228
+
229
+ /**
230
+ * Create and show the popover menu
231
+ */
232
+ private createAndShowPopover(): HTMLElement {
233
+ const popover = document.createElement('div');
234
+ popover.className = 'custom-popover-menu';
235
+ popover.innerHTML = `
236
+ <style>
237
+ .custom-popover-menu {
238
+ position: fixed;
239
+ background: white;
240
+ border: 1px solid #ccc;
241
+ border-radius: 6px;
242
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
243
+ min-width: 180px;
244
+ z-index: 10000;
245
+ }
246
+
247
+ .menu-item {
248
+ padding: 10px 16px;
249
+ cursor: pointer;
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: space-between;
253
+ transition: background-color 0.2s;
254
+ position: relative;
255
+ font-size: 14px;
256
+ color: #333;
257
+ }
258
+
259
+ .menu-item:hover {
260
+ background: #f5f5f5;
261
+ }
262
+
263
+ .menu-item.disabled {
264
+ opacity: 0.5;
265
+ cursor: not-allowed;
266
+ pointer-events: none;
267
+ }
268
+
269
+ .menu-item.has-submenu:hover .submenu {
270
+ display: block;
271
+ }
272
+
273
+ .menu-item-label {
274
+ flex: 1;
275
+ }
276
+
277
+ .menu-item-arrow {
278
+ margin-left: 12px;
279
+ font-size: 10px;
280
+ color: #666;
281
+ }
282
+
283
+ .menu-separator {
284
+ height: 1px;
285
+ background: #e0e0e0;
286
+ margin: 4px 8px;
287
+ }
288
+
289
+ .submenu {
290
+ display: none;
291
+ position: fixed;
292
+ background: white;
293
+ border: 1px solid #ccc;
294
+ border-radius: 6px;
295
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
296
+ min-width: 180px;
297
+ z-index: 10001;
298
+ }
299
+ </style>
300
+ ${this.renderMenuItems(this.menuItems)}
301
+ `;
302
+
303
+ return popover;
304
+ }
305
+
306
+ /**
307
+ * Attach event listeners to menu items
308
+ */
309
+ private attachMenuListeners(popover: HTMLElement, items: PopoverMenuItem[]): void {
310
+ const menuItems = popover.querySelectorAll('.menu-item:not(.has-submenu)');
311
+
312
+ menuItems.forEach((element, index) => {
313
+ let flatIndex = 0;
314
+ const findItem = (items: PopoverMenuItem[]): PopoverMenuItem | null => {
315
+ for (const item of items) {
316
+ if (item.label === '---sep') continue;
317
+ if (!(item.items && item.items.length > 0)) {
318
+ if (flatIndex === index) return item;
319
+ flatIndex++;
320
+ }
321
+ }
322
+ return null;
323
+ };
324
+
325
+ const item = findItem(items);
326
+ if (item && item.onclick) {
327
+ element.addEventListener('click', (e) => {
328
+ e.stopPropagation();
329
+ item.onclick!();
330
+ this.hideMenu();
331
+ });
332
+ }
333
+ });
334
+
335
+ // Handle submenu positioning within container boundaries
336
+ const containerRect = this.getBoundingClientRect();
337
+ const submenuItems = popover.querySelectorAll('.menu-item.has-submenu');
338
+
339
+ submenuItems.forEach(element => {
340
+ element.addEventListener('mouseenter', () => {
341
+ const submenu = element.querySelector('.submenu') as HTMLElement;
342
+ if (submenu) {
343
+ const rect = element.getBoundingClientRect();
344
+ const submenuRect = submenu.getBoundingClientRect();
345
+
346
+ let left = rect.right + 5;
347
+ let top = rect.top;
348
+
349
+ // Check if submenu would overflow container on the right
350
+ if (left + submenuRect.width > containerRect.right) {
351
+ // Try positioning to the left of the parent item
352
+ left = rect.left - submenuRect.width - 5;
353
+
354
+ // If still overflowing left, position at container left edge
355
+ if (left < containerRect.left) {
356
+ left = containerRect.left;
357
+ }
358
+ }
359
+
360
+ // Check if submenu would overflow container at the bottom
361
+ if (top + submenuRect.height > containerRect.bottom) {
362
+ // Align bottom of submenu with bottom of container
363
+ top = containerRect.bottom - submenuRect.height;
364
+
365
+ // If still overflowing at top, position at container top
366
+ if (top < containerRect.top) {
367
+ top = containerRect.top;
368
+ }
369
+ }
370
+
371
+ submenu.style.left = `${left}px`;
372
+ submenu.style.top = `${top}px`;
373
+ }
374
+ });
375
+ });
376
+ }
377
+
378
+ /**
379
+ * Update menu button position
380
+ */
381
+ private updateMenuButtonPosition(): void {
382
+ if (!this.menuButton) return;
383
+
384
+ this.menuButton.className = `menu-button ${this.menuPosition} ${this.alwaysShowMenu ? 'always-visible' : ''}`;
385
+ }
386
+
387
+ /**
388
+ * Update menu button visibility
389
+ */
390
+ private updateMenuButtonVisibility(): void {
391
+ if (!this.menuButton) return;
392
+
393
+ if (this.alwaysShowMenu) {
394
+ this.menuButton.classList.add('always-visible');
395
+ } else {
396
+ this.menuButton.classList.remove('always-visible');
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Setup event listeners
402
+ */
403
+ private setupEventListeners(): void {
404
+ if (this.menuButton) {
405
+ this.menuButton.addEventListener('click', this.handleMenuButtonClick.bind(this));
406
+ }
407
+
408
+ // Allow clicks to pass through to slotted content
409
+ const contentWrapper = this.shadowRoot.querySelector('.content-wrapper');
410
+ if (contentWrapper) {
411
+ contentWrapper.addEventListener('click', this.handleContentClick.bind(this));
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Cleanup event listeners
417
+ */
418
+ private cleanupEventListeners(): void {
419
+ if (this.menuButton) {
420
+ this.menuButton.removeEventListener('click', this.handleMenuButtonClick.bind(this));
421
+ }
422
+
423
+ const contentWrapper = this.shadowRoot.querySelector('.content-wrapper');
424
+ if (contentWrapper) {
425
+ contentWrapper.removeEventListener('click', this.handleContentClick.bind(this));
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Handle menu button click
431
+ */
432
+ private handleMenuButtonClick(e: Event): void {
433
+ e.stopPropagation();
434
+
435
+ if (!this.menuButton) return;
436
+
437
+ // Toggle menu visibility
438
+ if (this.popoverMenu) {
439
+ this.hideMenu();
440
+ } else {
441
+ this.showMenu();
442
+ }
443
+ }
444
+
445
+ /**
446
+ * Show the menu
447
+ */
448
+ private showMenu(): void {
449
+ if (!this.menuButton || this.menuItems.length === 0) return;
450
+
451
+ // Create the popover
452
+ if (this.popoverMenu) {
453
+ this.popoverMenu.remove();
454
+ }
455
+
456
+ this.popoverMenu = this.createAndShowPopover() as any;
457
+ document.body.appendChild(this.popoverMenu as any);
458
+
459
+ // Get button and container bounds
460
+ const buttonRect = this.menuButton.getBoundingClientRect();
461
+ const containerRect = this.getBoundingClientRect();
462
+
463
+ // Temporarily position to measure
464
+ (this.popoverMenu as any).style.left = `${buttonRect.left}px`;
465
+ (this.popoverMenu as any).style.top = `${buttonRect.bottom + 4}px`;
466
+
467
+ // Wait for next frame to get accurate measurements
468
+ requestAnimationFrame(() => {
469
+ const menuRect = (this.popoverMenu as any).getBoundingClientRect();
470
+
471
+ let left = buttonRect.left;
472
+ let top = buttonRect.bottom + 4;
473
+
474
+ // Check if menu would overflow container on the right
475
+ if (left + menuRect.width > containerRect.right) {
476
+ // Try to align right edge of menu with right edge of container
477
+ left = containerRect.right - menuRect.width;
478
+
479
+ // If still overflowing left, align with left edge of container
480
+ if (left < containerRect.left) {
481
+ left = containerRect.left;
482
+ }
483
+ }
484
+
485
+ // Check if menu would overflow container on the left
486
+ if (left < containerRect.left) {
487
+ left = containerRect.left;
488
+ }
489
+
490
+ // Check if menu would overflow container at the bottom
491
+ if (top + menuRect.height > containerRect.bottom) {
492
+ // Try positioning above the button
493
+ top = buttonRect.top - menuRect.height - 4;
494
+
495
+ // If still overflowing at top, position at container top
496
+ if (top < containerRect.top) {
497
+ top = containerRect.top;
498
+ }
499
+ }
500
+
501
+ // Check if menu would overflow container at the top
502
+ if (top < containerRect.top) {
503
+ top = containerRect.top;
504
+ }
505
+
506
+ // Apply final position
507
+ (this.popoverMenu as any).style.left = `${left}px`;
508
+ (this.popoverMenu as any).style.top = `${top}px`;
509
+ });
510
+
511
+ // Attach event listeners
512
+ this.attachMenuListeners(this.popoverMenu as any, this.menuItems);
513
+
514
+ // Add click listener to close menu when clicking outside
515
+ setTimeout(() => {
516
+ document.addEventListener('click', this.handleDocumentClick.bind(this), { once: true });
517
+ }, 0);
518
+ }
519
+
520
+ /**
521
+ * Hide the menu
522
+ */
523
+ private hideMenu(): void {
524
+ if (this.popoverMenu) {
525
+ (this.popoverMenu as any).remove();
526
+ this.popoverMenu = null;
527
+ }
528
+ }
529
+
530
+ /**
531
+ * Handle document click to close menu
532
+ */
533
+ private handleDocumentClick(e: Event): void {
534
+ const target = e.target as Node;
535
+ const popoverElement = this.popoverMenu as any;
536
+ if (popoverElement && !popoverElement.contains(target) && !this.menuButton?.contains(target)) {
537
+ this.hideMenu();
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Handle content click - pass through to slotted elements
543
+ */
544
+ private handleContentClick(e: Event): void {
545
+ // Get the slotted elements
546
+ const slot = this.shadowRoot.querySelector('slot');
547
+ if (!slot) return;
548
+
549
+ const assignedElements = slot.assignedElements();
550
+ if (assignedElements.length === 0) return;
551
+
552
+ // The click naturally propagates to slotted content
553
+ // We just need to ensure it doesn't trigger the menu
554
+ e.stopPropagation();
555
+ }
556
+ }
557
+
558
+ /**
559
+ * Conditionally defines the custom element if in a browser environment.
560
+ */
561
+ const defineContainerBox = (tagName = 'liwe3-container-box'): void => {
562
+ if (typeof window !== 'undefined' && !window.customElements.get(tagName)) {
563
+ customElements.define(tagName, ContainerBoxElement);
564
+ }
565
+ };
566
+
567
+ // Auto-register with default tag name
568
+ defineContainerBox();
569
+
570
+ export { defineContainerBox };