@digitalwalletcorp/vue-core 1.2.1 โ†’ 1.3.1

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 (188) hide show
  1. package/README.md +79 -3
  2. package/lib/accordion-fieldset.d.cts +14 -4
  3. package/lib/accordion-fieldset.d.ts +14 -4
  4. package/lib/accordion-section.d.cts +20 -10
  5. package/lib/accordion-section.d.ts +20 -10
  6. package/lib/components-BuTJ1wX8.js +26 -0
  7. package/lib/components-CKql5lWg.cjs +1 -0
  8. package/lib/components.d.cts +10 -0
  9. package/lib/components.d.ts +10 -0
  10. package/lib/copy-button.d.cts +34 -0
  11. package/lib/copy-button.d.ts +34 -0
  12. package/lib/dark-mode-selector.d.cts +32 -0
  13. package/lib/dark-mode-selector.d.ts +32 -0
  14. package/lib/data-table.d.cts +29 -0
  15. package/lib/data-table.d.ts +29 -0
  16. package/lib/help-button.d.cts +39 -0
  17. package/lib/help-button.d.ts +39 -0
  18. package/lib/help-popper.d.cts +39 -0
  19. package/lib/help-popper.d.ts +39 -0
  20. package/lib/helpers/data-table-csv.d.cts +17 -0
  21. package/lib/helpers/data-table-csv.d.ts +17 -0
  22. package/lib/helpers/show-floating-component.d.cts +86 -0
  23. package/lib/helpers/show-floating-component.d.ts +86 -0
  24. package/lib/helpers/show-modal-dialog.d.cts +73 -0
  25. package/lib/helpers/show-modal-dialog.d.ts +73 -0
  26. package/lib/helpers/show-overlay-box.d.cts +53 -0
  27. package/lib/helpers/show-overlay-box.d.ts +53 -0
  28. package/lib/helpers/show-screen-loading.d.cts +20 -0
  29. package/lib/helpers/show-screen-loading.d.ts +20 -0
  30. package/lib/helpers/show-snackbar.d.cts +47 -0
  31. package/lib/helpers/show-snackbar.d.ts +47 -0
  32. package/lib/hourglass-loading.d.cts +1 -1
  33. package/lib/hourglass-loading.d.ts +1 -1
  34. package/lib/index.cjs +1 -1
  35. package/lib/index.d.cts +34 -0
  36. package/lib/index.d.ts +34 -0
  37. package/lib/index.js +445 -18
  38. package/lib/internal/anchored-popover.d.cts +35 -0
  39. package/lib/internal/anchored-popover.d.ts +35 -0
  40. package/lib/internal/anchored-position.d.cts +50 -0
  41. package/lib/internal/anchored-position.d.ts +50 -0
  42. package/lib/internal/data-table-controls.d.cts +42 -0
  43. package/lib/internal/data-table-controls.d.ts +42 -0
  44. package/lib/internal/data-table-value.d.cts +32 -0
  45. package/lib/internal/data-table-value.d.ts +32 -0
  46. package/lib/internal/floating-component.d.cts +52 -0
  47. package/lib/internal/floating-component.d.ts +52 -0
  48. package/lib/internal/icon-popper.d.cts +32 -0
  49. package/lib/internal/icon-popper.d.ts +32 -0
  50. package/lib/internal/mount-window.d.cts +39 -0
  51. package/lib/internal/mount-window.d.ts +39 -0
  52. package/lib/internal/movable-window.d.cts +55 -0
  53. package/lib/internal/movable-window.d.ts +55 -0
  54. package/lib/internal/opened-overlay-boxes.d.cts +2 -0
  55. package/lib/internal/opened-overlay-boxes.d.ts +2 -0
  56. package/lib/internal/pagination.d.cts +22 -0
  57. package/lib/internal/pagination.d.ts +22 -0
  58. package/lib/internal/snackbar-container.d.cts +20 -0
  59. package/lib/internal/snackbar-container.d.ts +20 -0
  60. package/lib/internal/snackbar-item.d.cts +17 -0
  61. package/lib/internal/snackbar-item.d.ts +17 -0
  62. package/lib/internal/tab-group-context.d.cts +4 -2
  63. package/lib/internal/tab-group-context.d.ts +4 -2
  64. package/lib/internal/use-movable-window.d.cts +44 -0
  65. package/lib/internal/use-movable-window.d.ts +44 -0
  66. package/lib/internal/window-order.d.cts +6 -0
  67. package/lib/internal/window-order.d.ts +6 -0
  68. package/lib/intersection-lazy-component.d.cts +32 -0
  69. package/lib/intersection-lazy-component.d.ts +32 -0
  70. package/lib/label-button.d.cts +2 -2
  71. package/lib/label-button.d.ts +2 -2
  72. package/lib/label-icon.d.cts +2 -2
  73. package/lib/label-icon.d.ts +2 -2
  74. package/lib/modal-dialog.d.cts +67 -0
  75. package/lib/modal-dialog.d.ts +67 -0
  76. package/lib/nuxt.cjs +1 -1
  77. package/lib/nuxt.js +1 -1
  78. package/lib/overlay-box.d.cts +52 -0
  79. package/lib/overlay-box.d.ts +52 -0
  80. package/lib/page-section.d.cts +2 -2
  81. package/lib/page-section.d.ts +2 -2
  82. package/lib/page-title.d.cts +2 -2
  83. package/lib/page-title.d.ts +2 -2
  84. package/lib/register.cjs +1 -1
  85. package/lib/register.js +1 -1
  86. package/lib/screen-loading.d.cts +7 -0
  87. package/lib/screen-loading.d.ts +7 -0
  88. package/lib/style.css +1 -1
  89. package/lib/tab-content.d.cts +5 -5
  90. package/lib/tab-content.d.ts +5 -5
  91. package/lib/tab-group.d.cts +7 -10
  92. package/lib/tab-group.d.ts +7 -10
  93. package/lib/types/data-table.d.cts +185 -0
  94. package/lib/types/data-table.d.ts +185 -0
  95. package/lib/types/modal-dialog.d.cts +13 -0
  96. package/lib/types/modal-dialog.d.ts +13 -0
  97. package/lib/types/movable-window.d.cts +16 -0
  98. package/lib/types/movable-window.d.ts +16 -0
  99. package/lib/warning-popper.d.cts +39 -0
  100. package/lib/warning-popper.d.ts +39 -0
  101. package/lib/warning-popper.vue_vue_type_style_index_0_lang-BKV_FX6k.js +1837 -0
  102. package/lib/warning-popper.vue_vue_type_style_index_0_lang-CHmkjVCO.cjs +1 -0
  103. package/package.json +40 -14
  104. package/src/accordion-fieldset.vue +24 -19
  105. package/src/accordion-section.vue +33 -28
  106. package/src/components.ts +10 -0
  107. package/src/copy-button.vue +89 -0
  108. package/src/dark-mode-selector.vue +212 -0
  109. package/src/data-table.vue +648 -0
  110. package/src/help-button.vue +128 -0
  111. package/src/help-popper.vue +70 -0
  112. package/src/helpers/data-table-csv.ts +55 -0
  113. package/src/helpers/show-floating-component.ts +177 -0
  114. package/src/helpers/show-modal-dialog.ts +121 -0
  115. package/src/helpers/show-overlay-box.ts +106 -0
  116. package/src/helpers/show-screen-loading.ts +37 -0
  117. package/src/helpers/show-snackbar.ts +153 -0
  118. package/src/hourglass-loading.vue +1 -1
  119. package/src/index.ts +34 -0
  120. package/src/internal/anchored-popover.vue +192 -0
  121. package/src/internal/anchored-position.ts +135 -0
  122. package/src/internal/data-table-controls.vue +203 -0
  123. package/src/internal/data-table-value.ts +99 -0
  124. package/src/internal/floating-component.vue +202 -0
  125. package/src/internal/icon-popper.vue +185 -0
  126. package/src/internal/mount-window.ts +110 -0
  127. package/src/internal/movable-window.vue +315 -0
  128. package/src/internal/opened-overlay-boxes.ts +2 -0
  129. package/src/internal/pagination.vue +325 -0
  130. package/src/internal/snackbar-container.vue +258 -0
  131. package/src/internal/snackbar-item.ts +20 -0
  132. package/src/internal/tab-group-context.ts +4 -2
  133. package/src/internal/use-movable-window.ts +208 -0
  134. package/src/internal/window-order.ts +11 -0
  135. package/src/intersection-lazy-component.vue +84 -0
  136. package/src/label-button.vue +9 -6
  137. package/src/label-icon.vue +2 -2
  138. package/src/modal-dialog.vue +287 -0
  139. package/src/overlay-box.vue +218 -0
  140. package/src/page-section.vue +7 -7
  141. package/src/page-title.vue +4 -4
  142. package/src/screen-loading.vue +90 -0
  143. package/src/tab-content.vue +16 -15
  144. package/src/tab-group.vue +34 -36
  145. package/src/types/data-table.ts +196 -0
  146. package/src/types/modal-dialog.ts +16 -0
  147. package/src/types/movable-window.ts +18 -0
  148. package/src/warning-popper.vue +70 -0
  149. package/lib/accordion-fieldset.cjs +0 -1
  150. package/lib/accordion-fieldset.js +0 -4
  151. package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-Cf4czDXz.js +0 -66
  152. package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-DoM5QjpJ.cjs +0 -1
  153. package/lib/accordion-section.cjs +0 -1
  154. package/lib/accordion-section.js +0 -4
  155. package/lib/accordion-section.vue_vue_type_style_index_0_lang-CFDdUEnn.cjs +0 -1
  156. package/lib/accordion-section.vue_vue_type_style_index_0_lang-Gvjjx02P.js +0 -78
  157. package/lib/components-C63HJoCn.cjs +0 -1
  158. package/lib/components-q4Cf97bO.js +0 -24
  159. package/lib/hourglass-loading.cjs +0 -1
  160. package/lib/hourglass-loading.js +0 -4
  161. package/lib/hourglass-loading.vue_vue_type_style_index_0_lang-C72UVA9W.cjs +0 -1
  162. package/lib/hourglass-loading.vue_vue_type_style_index_0_lang-DkUGIxQ2.js +0 -22
  163. package/lib/label-button.cjs +0 -1
  164. package/lib/label-button.js +0 -4
  165. package/lib/label-button.vue_vue_type_style_index_0_lang-D7ZgfZOL.cjs +0 -1
  166. package/lib/label-button.vue_vue_type_style_index_0_lang-DqRYddVt.js +0 -44
  167. package/lib/label-icon.cjs +0 -1
  168. package/lib/label-icon.js +0 -4
  169. package/lib/label-icon.vue_vue_type_style_index_0_lang-D9Cimu20.cjs +0 -1
  170. package/lib/label-icon.vue_vue_type_style_index_0_lang-me52HE2V.js +0 -38
  171. package/lib/page-section.cjs +0 -1
  172. package/lib/page-section.js +0 -4
  173. package/lib/page-section.vue_vue_type_style_index_0_lang-DEAkTLxd.cjs +0 -1
  174. package/lib/page-section.vue_vue_type_style_index_0_lang-DpVQe_rV.js +0 -54
  175. package/lib/page-title.cjs +0 -1
  176. package/lib/page-title.js +0 -4
  177. package/lib/page-title.vue_vue_type_style_index_0_lang-BqIsIks5.cjs +0 -1
  178. package/lib/page-title.vue_vue_type_style_index_0_lang-ChZot85K.js +0 -36
  179. package/lib/tab-content.cjs +0 -1
  180. package/lib/tab-content.js +0 -4
  181. package/lib/tab-content.vue_vue_type_style_index_0_lang-BeCi7Xkp.cjs +0 -1
  182. package/lib/tab-content.vue_vue_type_style_index_0_lang-CcQLHmIF.js +0 -44
  183. package/lib/tab-group.cjs +0 -1
  184. package/lib/tab-group.js +0 -4
  185. package/lib/tab-group.vue_vue_type_style_index_0_lang-C84mDEOC.js +0 -103
  186. package/lib/tab-group.vue_vue_type_style_index_0_lang-CMaufRJV.cjs +0 -1
  187. package/lib/use-shrinkable-CS2bmsJJ.js +0 -17
  188. package/lib/use-shrinkable-Cu9JQZll.cjs +0 -1
@@ -0,0 +1,208 @@
1
+ import { onBeforeUnmount, reactive, ref } from 'vue';
2
+ import type { Ref } from 'vue';
3
+ import type { MovableWindowDragMode } from '@/types/movable-window';
4
+
5
+ /** ใƒชใ‚ตใ‚คใ‚บใงๆŽดใ‚“ใงใ„ใ‚‹่ง’ */
6
+ export type MovableWindowCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
7
+
8
+ interface MovableWindowOptions<T extends HTMLElement = HTMLElement> {
9
+ /** ใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆๆœฌไฝ“ใฎ่ฆ็ด ใ€‚ใƒ‰ใƒฉใƒƒใ‚ฐ็ต‚ไบ†ๆ™‚ใซ็”ป้ขๅ†…ใธๆˆปใ™ๅˆคๅฎšใจใ€ใƒชใ‚ตใ‚คใ‚บใฎ่ตท็‚นใฎๅฏธๆณ•ใซไฝฟใ† */
10
+ target: Ref<T | undefined>;
11
+ /** ใƒ‰ใƒฉใƒƒใ‚ฐใƒขใƒผใƒ‰ใ‚’่ฟ”ใ™้–ขๆ•ฐใ€‚'body' / 'header' ใฎใฉใกใ‚‰ใงใ‚‚ใชใ„ๅ ดๅˆใฏใƒ‰ใƒฉใƒƒใ‚ฐใงใใชใ„ */
12
+ dragMode: () => MovableWindowDragMode | undefined;
13
+ /** ใƒชใ‚ตใ‚คใ‚บๆ™‚ใฎๆœ€ๅฐๅน…(px) */
14
+ minWidth?: number;
15
+ /** ใƒชใ‚ตใ‚คใ‚บๆ™‚ใฎๆœ€ๅฐ้ซ˜ใ•(px) */
16
+ minHeight?: number;
17
+ /**
18
+ * ใƒ‰ใƒฉใƒƒใ‚ฐ็ต‚ไบ†ๆ™‚ใซไธ‹็ซฏใ‚‚็”ป้ขๅ†…ใธๆˆปใ™ใ‹ใ€‚
19
+ * ใ‚นใ‚ฏใƒญใƒผใƒซใง้ ˜ๅŸŸใŒๅบƒใŒใ‚‹้€šๅธธใฎใƒšใƒผใ‚ธไธŠใงใฏ falseใ€็”ป้ขใซๅ›บๅฎšใ—ใŸใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆใงใฏ true ใซใ™ใ‚‹
20
+ */
21
+ clampBottom?: boolean;
22
+ }
23
+
24
+ /**
25
+ * ใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆใฎใƒ‰ใƒฉใƒƒใ‚ฐใซใ‚ˆใ‚‹็งปๅ‹•ใจใ€่ง’ใฎใคใพใฟใซใ‚ˆใ‚‹ใƒชใ‚ตใ‚คใ‚บใ‚’ๆ‰ฑใ†ใ€‚
26
+ * ใƒžใ‚ฆใ‚นใƒปใ‚ฟใƒƒใƒใƒปใƒšใƒณใ‚’ Pointer Events ใงใพใจใ‚ใฆๆ‰ฑใ†ใ€‚
27
+ * ไฝ็ฝฎใƒปใ‚ตใ‚คใ‚บใฎใƒชใ‚ขใ‚ฏใƒ†ใ‚ฃใƒ–ใช็Šถๆ…‹ใจใ€ใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆใฎ pointerdown ใซ็ตใณไป˜ใ‘ใ‚‹้–‹ๅง‹ใƒใƒณใƒ‰ใƒฉใ‚’่ฟ”ใ™ใ€‚
28
+ * ๅˆๆœŸไฝ็ฝฎใƒปๅˆๆœŸใ‚ตใ‚คใ‚บใฏๅ‘ผใณๅ‡บใ—ๅดใŒๆฑบใ‚ใ‚‹
29
+ *
30
+ * @param {MovableWindowOptions<T>} options
31
+ */
32
+ export function useMovableWindow<T extends HTMLElement = HTMLElement>(options: MovableWindowOptions<T>) {
33
+ const minWidth = options.minWidth ?? 20;
34
+ const minHeight = options.minHeight ?? 20;
35
+
36
+ const moving = ref(false);
37
+ const resizing = ref(false);
38
+
39
+ const currentPosition = reactive({
40
+ x: 0,
41
+ y: 0
42
+ });
43
+
44
+ /** ๅน…ใƒป้ซ˜ใ•(px)ใ€‚-1 ใฏๅฏธๆณ•ใ‚’ๆŒ‡ๅฎšใ›ใšไธญ่บซใซๅˆใ‚ใ›ใ‚‹ */
45
+ const currentRect = reactive({
46
+ width: -1,
47
+ height: -1
48
+ });
49
+
50
+ /** ๆ“ไฝœไธญใฎใƒใ‚คใƒณใ‚ฟใ€‚2ๆœฌ็›ฎใฎๆŒ‡ใชใฉใ€ๅˆฅใฎใƒใ‚คใƒณใ‚ฟใฎๅ‹•ใใ‚’ๆ‹พใ‚ใชใ„ใ‚ˆใ†ใซใ™ใ‚‹ */
51
+ let activePointerId: number | null = null;
52
+ let resizingCorner: MovableWindowCorner = 'bottom-right';
53
+ let previousPointer = {
54
+ x: 0,
55
+ y: 0
56
+ };
57
+
58
+ const onPointerMove = (event: PointerEvent): void => {
59
+ if (event.pointerId !== activePointerId) {
60
+ return;
61
+ }
62
+ event.preventDefault();
63
+ const movementX = event.clientX - previousPointer.x;
64
+ const movementY = event.clientY - previousPointer.y;
65
+ previousPointer = {
66
+ x: event.clientX,
67
+ y: event.clientY
68
+ };
69
+ if (moving.value) {
70
+ currentPosition.x += movementX;
71
+ currentPosition.y += movementY;
72
+ } else if (resizing.value) {
73
+ // ๅทฆใƒปไธŠใฎ่พบใ‚’ๆŽดใ‚“ใงใ„ใ‚‹ใจใใฏใ€ๅฎŸ้š›ใซ็ธฎใ‚“ใ ๅˆ†ใ ใ‘ไฝ็ฝฎใ‚’ใšใ‚‰ใ™ใ€‚ๆœ€ๅฐใ‚ตใ‚คใ‚บใซๅฝ“ใŸใฃใŸใ‚‰ไฝ็ฝฎใ‚‚ๆญขใพใ‚‹
74
+ if (resizingCorner.endsWith('left')) {
75
+ const width = Math.max(minWidth, currentRect.width - movementX);
76
+ currentPosition.x += currentRect.width - width;
77
+ currentRect.width = width;
78
+ } else {
79
+ currentRect.width = Math.max(minWidth, currentRect.width + movementX);
80
+ }
81
+ if (resizingCorner.startsWith('top')) {
82
+ const height = Math.max(minHeight, currentRect.height - movementY);
83
+ currentPosition.y += currentRect.height - height;
84
+ currentRect.height = height;
85
+ } else {
86
+ currentRect.height = Math.max(minHeight, currentRect.height + movementY);
87
+ }
88
+ }
89
+ };
90
+
91
+ /**
92
+ * ใƒ‰ใƒฉใƒƒใ‚ฐใง็”ป้ขใฎๅค–ใธๅ‡บใ—ใ™ใŽใŸใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆใ‚’ใ€ๆŽดใ‚ใ‚‹ไฝ็ฝฎใพใงๆˆปใ™
93
+ */
94
+ const clampPosition = (): void => {
95
+ const width = options.target.value?.getBoundingClientRect().width || 0;
96
+ if (currentPosition.x < 40 - width) {
97
+ currentPosition.x = 40 - width;
98
+ }
99
+ if (window.innerWidth - 40 < currentPosition.x) {
100
+ currentPosition.x = window.innerWidth - 40;
101
+ }
102
+ if (currentPosition.y < 0) {
103
+ currentPosition.y = 0;
104
+ }
105
+ if (options.clampBottom && window.innerHeight - 20 < currentPosition.y) {
106
+ currentPosition.y = window.innerHeight - 20;
107
+ }
108
+ };
109
+
110
+ const onPointerEnd = (event: PointerEvent): void => {
111
+ if (event.pointerId !== activePointerId) {
112
+ return;
113
+ }
114
+ const wasMoving = moving.value;
115
+ teardown();
116
+ if (wasMoving) {
117
+ clampPosition();
118
+ }
119
+ };
120
+
121
+ /**
122
+ * ็™ป้Œฒไธญใฎใƒ‰ใƒฉใƒƒใ‚ฐใƒปใƒชใ‚ตใ‚คใ‚บใฎใƒชใ‚นใƒŠใƒผใ‚’ใ™ในใฆ่งฃ้™คใ™ใ‚‹ใ€‚
123
+ * ใ‚ขใƒณใƒžใ‚ฆใƒณใƒˆใ‚’ๅพ…ใŸใšใซ่งฃ้™คใ—ใŸใ„ใจใ(ใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆใ‚’้–‰ใ˜ใŸใจใใชใฉ)ใซๅ‘ผใถ
124
+ */
125
+ const teardown = (): void => {
126
+ document.removeEventListener('pointermove', onPointerMove, true);
127
+ document.removeEventListener('pointerup', onPointerEnd, true);
128
+ document.removeEventListener('pointercancel', onPointerEnd, true);
129
+ activePointerId = null;
130
+ moving.value = false;
131
+ resizing.value = false;
132
+ };
133
+
134
+ const start = (event: PointerEvent): void => {
135
+ teardown();
136
+ activePointerId = event.pointerId;
137
+ // ๆŠผใ—ใŸไฝ็ฝฎใ‚’็งปๅ‹•้‡ใฎ่ตท็‚นใซใ™ใ‚‹ใ€‚่ตท็‚นใŒ็„กใ„ใจๆœ€ๅˆใฎ็งปๅ‹•้‡ใŒๆจใฆใ‚‰ใ‚Œใ‚‹
138
+ previousPointer = {
139
+ x: event.clientX,
140
+ y: event.clientY
141
+ };
142
+ document.addEventListener('pointermove', onPointerMove, true);
143
+ document.addEventListener('pointerup', onPointerEnd, true);
144
+ document.addEventListener('pointercancel', onPointerEnd, true);
145
+ };
146
+
147
+ /**
148
+ * ใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆๅ…จไฝ“ใ‚’ๆŽดใ‚“ใ ใจใใฎใƒ‰ใƒฉใƒƒใ‚ฐ้–‹ๅง‹
149
+ *
150
+ * @param {PointerEvent} event
151
+ */
152
+ const onDragStart = (event: PointerEvent): void => {
153
+ if (event.isPrimary && options.dragMode() === 'body') {
154
+ start(event);
155
+ moving.value = true;
156
+ }
157
+ };
158
+
159
+ /**
160
+ * ใƒ˜ใƒƒใƒ€ใ‚’ๆŽดใ‚“ใ ใจใใฎใƒ‰ใƒฉใƒƒใ‚ฐ้–‹ๅง‹
161
+ *
162
+ * @param {PointerEvent} event
163
+ */
164
+ const onDragHeaderStart = (event: PointerEvent): void => {
165
+ if (event.isPrimary && options.dragMode() === 'header') {
166
+ start(event);
167
+ moving.value = true;
168
+ }
169
+ };
170
+
171
+ /**
172
+ * ใƒชใ‚ตใ‚คใ‚บ้–‹ๅง‹
173
+ *
174
+ * @param {PointerEvent} event
175
+ * @param {MovableWindowCorner} [corner] ๆŽดใ‚“ใ ่ง’ใ€‚ๆ—ขๅฎšใฏๅณไธ‹
176
+ */
177
+ const onResizeStart = (event: PointerEvent, corner: MovableWindowCorner = 'bottom-right'): void => {
178
+ if (!event.isPrimary) {
179
+ return;
180
+ }
181
+ resizingCorner = corner;
182
+ // ๅน…ใƒป้ซ˜ใ•ใŒๆœชๆŒ‡ๅฎš(-1)ใฎใพใพใ ใจ็งปๅ‹•้‡ใ‚’่ถณใ™่ตท็‚นใŒ็„กใๆœ€ๅฐใ‚ตใ‚คใ‚บใซๆฝฐใ‚Œใ‚‹ใŸใ‚ใ€ๅฎŸๅฏธใ‚’่ตท็‚นใซใ™ใ‚‹
183
+ const rect = options.target.value?.getBoundingClientRect();
184
+ if (rect) {
185
+ if (currentRect.width < 0) {
186
+ currentRect.width = rect.width;
187
+ }
188
+ if (currentRect.height < 0) {
189
+ currentRect.height = rect.height;
190
+ }
191
+ }
192
+ start(event);
193
+ resizing.value = true;
194
+ };
195
+
196
+ onBeforeUnmount(teardown);
197
+
198
+ return {
199
+ moving,
200
+ resizing,
201
+ currentPosition,
202
+ currentRect,
203
+ onDragStart,
204
+ onDragHeaderStart,
205
+ onResizeStart,
206
+ teardown
207
+ };
208
+ }
@@ -0,0 +1,11 @@
1
+ let lastOrder = 0;
2
+
3
+ /**
4
+ * ใ‚ฆใ‚ฃใƒณใƒ‰ใ‚ฆ(OverlayBox / FloatingComponent)ใฎ้‡ใชใ‚Š้ †ใ‚’่ฟ”ใ™ใ€‚ๅพŒใ‹ใ‚‰ๅ‘ผใ‚“ใ ใ‚‚ใฎใปใฉๅคงใใใ€ๅ‰้ขใซๅ‡บใ‚‹
5
+ *
6
+ * @returns {number}
7
+ */
8
+ export const nextWindowOrder = (): number => {
9
+ lastOrder += 1;
10
+ return lastOrder;
11
+ };
@@ -0,0 +1,84 @@
1
+ <!--
2
+ ใ‚นใ‚ฏใƒญใƒผใƒซใซๅฟœใ˜ใฆใ€ๅฝ“่ฉฒ้ ˜ๅŸŸใŒ็”ป้ข่กจ็คบ้ ˜ๅŸŸใซใชใฃใŸใจใใซใ‚ณใƒณใƒ†ใƒณใƒ„ใ‚’ๆ็”ปใ™ใ‚‹ใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ
3
+ ไธ€ๅบฆๆ็”ปใ—ใŸใ‚‰ใ€่กจ็คบ้ ˜ๅŸŸใ‹ใ‚‰ๅค–ใ‚Œใฆใ‚‚ๆ็”ปใ—ใŸใพใพใซใ™ใ‚‹ใ€‚
4
+ IntersectionObserver ใฏใƒ–ใƒฉใ‚ฆใ‚ถใซใ—ใ‹็„กใ„ใฎใงใ€ใƒžใ‚ฆใƒณใƒˆๅพŒใซ็”Ÿๆˆใ™ใ‚‹ใ€‚
5
+ root ใซใƒ†ใƒณใƒ—ใƒฌใƒผใƒˆๅ‚็…งใ‚’ๆธกใ™ใจใ€ใ“ใฎใ‚ณใƒณใƒใƒผใƒใƒณใƒˆใฎใƒžใ‚ฆใƒณใƒˆๆ™‚ใซใฏใพใ ่ฆ็ด ใŒๅ…ฅใฃใฆใ„ใชใ„ใŸใ‚ใ€ใ‚ชใƒ—ใ‚ทใƒงใƒณใŒๅค‰ใ‚ใฃใŸใ‚‰็›ฃ่ฆ–ใ‚’ใ‚„ใ‚Š็›ดใ™ใ€‚
6
+ -->
7
+ <template>
8
+ <div
9
+ ref="refTarget"
10
+ class="dwui-intersection-lazy-component"
11
+ >
12
+ <slot v-if="visible" />
13
+ <slot
14
+ v-else
15
+ name="placeholder"
16
+ />
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
22
+
23
+ export interface Props {
24
+ /** ไบคๅทฎใ‚’ๅˆคๅฎšใ™ใ‚‹ใ‚นใ‚ฏใƒญใƒผใƒซ้ ˜ๅŸŸใฎ่ฆ็ด ใ€‚ๆœชๆŒ‡ๅฎšใชใ‚‰ใƒ“ใƒฅใƒผใƒใƒผใƒˆ */
25
+ root?: Element | null;
26
+ /** ๅˆคๅฎšใ™ใ‚‹้ ˜ๅŸŸใ‚’ root ใฎ็ซฏใ‹ใ‚‰ๅบƒใ’ใ‚‹ใ€ใพใŸใฏ็‹ญใ‚ใ‚‹้‡ใ€‚CSS ใฎ margin ใจๅŒใ˜ๆ›ธๅผ */
27
+ rootMargin?: string;
28
+ /** ไธญ่บซใ‚’ๆ็”ปใ™ใ‚‹ไบคๅทฎใฎๅ‰ฒๅˆ(0ใ€œ1)ใ€‚้…ๅˆ—ใ‚‚ๆธกใ›ใ‚‹ */
29
+ threshold?: number | number[];
30
+ }
31
+ const props = defineProps<Props>();
32
+
33
+ export interface Emits {
34
+ /** ๅˆใ‚ใฆ็”ป้ขใซๅ…ฅใฃใฆไธญ่บซใ‚’ๆ็”ปใ—ใŸใจใใซ็™บ่กŒใ™ใ‚‹ */
35
+ (e: 'emit:visible'): void;
36
+ }
37
+ const emit = defineEmits<Emits>();
38
+
39
+ export interface Slots {
40
+ /** ็”ป้ขใซๅ…ฅใฃใฆใ‹ใ‚‰ๆ็”ปใ™ใ‚‹ไธญ่บซ */
41
+ default?(): unknown;
42
+ /** ็”ป้ขใซๅ…ฅใ‚‹ใพใงใฎ้–“ใซ่กจ็คบใ™ใ‚‹ไธญ่บซ */
43
+ placeholder?(): unknown;
44
+ }
45
+ defineSlots<Slots>();
46
+
47
+ const refTarget = ref<HTMLElement>();
48
+ const visible = ref(false);
49
+
50
+ let observer: IntersectionObserver | undefined;
51
+
52
+ const observe = (): void => {
53
+ observer?.disconnect();
54
+ observer = undefined;
55
+ if (!refTarget.value || visible.value) {
56
+ return;
57
+ }
58
+ observer = new IntersectionObserver((entries) => {
59
+ if (entries.some((entry) => entry.isIntersecting)) {
60
+ visible.value = true;
61
+ observer?.disconnect();
62
+ observer = undefined;
63
+ emit('emit:visible');
64
+ }
65
+ }, {
66
+ root: props.root,
67
+ rootMargin: props.rootMargin,
68
+ threshold: props.threshold
69
+ });
70
+ observer.observe(refTarget.value);
71
+ };
72
+
73
+ onMounted(() => {
74
+ observe();
75
+ });
76
+
77
+ onBeforeUnmount(() => {
78
+ observer?.disconnect();
79
+ });
80
+
81
+ watch(() => [props.root, props.rootMargin, props.threshold], () => {
82
+ observe();
83
+ }, { flush: 'post' });
84
+ </script>
@@ -2,7 +2,10 @@
2
2
  ใ‚ขใ‚คใ‚ณใƒณใจใƒฉใƒ™ใƒซใ‚’ๆŒใคใƒœใ‚ฟใƒณ
3
3
  -->
4
4
  <template>
5
- <button class="dwui-label-button">
5
+ <button
6
+ type="button"
7
+ class="dwui-label-button"
8
+ >
6
9
  <LabelIcon
7
10
  :preset="props.preset"
8
11
  :gap="props.gap"
@@ -33,7 +36,7 @@ import type { ClassValue, StyleValue } from 'vue';
33
36
  import LabelIcon from '@/label-icon.vue';
34
37
  import type { LabelPreset } from '@/types/label-preset';
35
38
 
36
- interface Props {
39
+ export interface Props {
37
40
  /** ใ‚ขใ‚คใ‚ณใƒณใจใƒฉใƒ™ใƒซใฎ็ต„ใฟๅˆใ‚ใ› */
38
41
  preset?: LabelPreset;
39
42
  /** ใ‚ขใ‚คใ‚ณใƒณใจใƒฉใƒ™ใƒซใฎ้–“้š”ใ€‚ๆœชๆŒ‡ๅฎšใชใ‚‰LabelIconใฎๆ—ขๅฎšๅ€ค(0.25em) */
@@ -49,7 +52,7 @@ interface Props {
49
52
  }
50
53
  const props = defineProps<Props>();
51
54
 
52
- interface Slots {
55
+ export interface Slots {
53
56
  icon?(): unknown;
54
57
  default?(): unknown;
55
58
  }
@@ -59,7 +62,7 @@ const slots = defineSlots<Slots>();
59
62
  <style>
60
63
  :where(.dwui-label-button) {
61
64
  display: inline-block;
62
- padding: 2px 6px;
65
+ padding: 0.17em 0.5em;
63
66
  border: 1px solid var(--dwui-border-color-label-button, light-dark(#8f8f8f, #6b6f76));
64
67
  border-radius: 3px;
65
68
  background: var(--dwui-background-label-button, light-dark(#f4f4f4, #3a3c40));
@@ -82,7 +85,7 @@ const slots = defineSlots<Slots>();
82
85
  }
83
86
 
84
87
  :where(.dwui-label-button:focus-visible) {
85
- outline: var(--dwui-width-focus-ring, 2px) solid var(--dwui-outline-color-focus-ring, Highlight);
86
- outline-offset: var(--dwui-offset-focus-ring, 2px);
88
+ outline: var(--dwui-outline-width-focus-ring, 2px) solid var(--dwui-outline-color-focus-ring, Highlight);
89
+ outline-offset: var(--dwui-outline-offset-focus-ring, 2px);
87
90
  }
88
91
  </style>
@@ -31,7 +31,7 @@
31
31
  import type { ClassValue, StyleValue } from 'vue';
32
32
  import type { LabelPreset } from '@/types/label-preset';
33
33
 
34
- interface Props {
34
+ export interface Props {
35
35
  /** ใ‚ขใ‚คใ‚ณใƒณใจใƒฉใƒ™ใƒซใฎ็ต„ใฟๅˆใ‚ใ› */
36
36
  preset?: LabelPreset;
37
37
  /** ใ‚ขใ‚คใ‚ณใƒณใจใƒฉใƒ™ใƒซใฎ้–“้š”ใ€‚ๆœชๆŒ‡ๅฎšใชใ‚‰ๆ—ขๅฎšๅ€ค(0.25em) */
@@ -47,7 +47,7 @@ interface Props {
47
47
  }
48
48
  const props = defineProps<Props>();
49
49
 
50
- interface Slots {
50
+ export interface Slots {
51
51
  icon?(): unknown;
52
52
  default?(): unknown;
53
53
  }
@@ -0,0 +1,287 @@
1
+ <!--
2
+ ใƒขใƒผใƒ€ใƒซใƒ€ใ‚คใ‚ขใƒญใ‚ฐ
3
+ ใƒ–ใƒฉใ‚ฆใ‚ถๆจ™ๆบ–ใฎ <dialog> ใ‚’ showModal() ใง้–‹ใใ€ใƒกใƒƒใ‚ปใƒผใ‚ธใจ OKใ€ใพใŸใฏ Yes / No ใฎใƒœใ‚ฟใƒณใ‚’่กจ็คบใ™ใ‚‹ใ€‚
4
+ ใƒœใ‚ฟใƒณใ‹ Esc ใง้–‰ใ˜ใ€้–‰ใ˜ใŸใƒœใ‚ฟใƒณใ‚’ close ใ‚คใƒ™ใƒณใƒˆใง็Ÿฅใ‚‰ใ›ใ‚‹ใ€‚
5
+ -->
6
+ <template>
7
+ <dialog
8
+ ref="refDialog"
9
+ class="dwui-modal-dialog"
10
+ :class="`dwui-modal-dialog-${props.type}`"
11
+ :aria-labelledby="props.title ? titleId : undefined"
12
+ :aria-describedby="bodyId"
13
+ @cancel="onCancelDialog"
14
+ @keydown="onKeydownDialog"
15
+ >
16
+ <div class="dwui-modal-dialog-header">
17
+ <span class="dwui-modal-dialog-icon">
18
+ <slot name="icon">
19
+ <component :is="icons[props.type]" />
20
+ </slot>
21
+ </span>
22
+ <template v-if="props.title">
23
+ <span
24
+ v-if="props.html"
25
+ :id="titleId"
26
+ class="dwui-modal-dialog-title"
27
+ v-html="props.title"
28
+ />
29
+ <span
30
+ v-else
31
+ :id="titleId"
32
+ class="dwui-modal-dialog-title"
33
+ >
34
+ {{ props.title }}
35
+ </span>
36
+ </template>
37
+ </div>
38
+ <div
39
+ :id="bodyId"
40
+ class="dwui-modal-dialog-body"
41
+ >
42
+ <slot>
43
+ <template
44
+ v-for="(text, index) in messages"
45
+ :key="index"
46
+ >
47
+ <p
48
+ v-if="props.html"
49
+ v-html="text"
50
+ />
51
+ <p v-else>{{ text }}</p>
52
+ </template>
53
+ <div
54
+ v-if="images.length"
55
+ class="dwui-modal-dialog-images"
56
+ >
57
+ <img
58
+ v-for="(item, index) in images"
59
+ :key="index"
60
+ :src="item.src"
61
+ :alt="item.alt"
62
+ >
63
+ </div>
64
+ </slot>
65
+ </div>
66
+ <div
67
+ ref="refButtons"
68
+ class="dwui-modal-dialog-buttons"
69
+ >
70
+ <button
71
+ v-for="button in buttons"
72
+ :key="button"
73
+ type="button"
74
+ class="dwui-modal-dialog-button"
75
+ :class="`dwui-modal-dialog-button-${button}`"
76
+ @click="onClickButton(button)"
77
+ >
78
+ {{ labels[button] }}
79
+ </button>
80
+ </div>
81
+ </dialog>
82
+ </template>
83
+
84
+ <script setup lang="ts">
85
+ import { computed, onMounted, ref, useId, watch } from 'vue';
86
+ import { SvgCritical, SvgInfo, SvgQuestion, SvgWarningSign } from '@digitalwalletcorp/vue-svg-icons';
87
+ import type { ModalDialogButton, ModalDialogImage, ModalDialogResult, ModalDialogType } from '@/types/modal-dialog';
88
+
89
+ export interface Props {
90
+ /** ใƒ€ใ‚คใ‚ขใƒญใ‚ฐใฎ็จฎ้กž */
91
+ type?: ModalDialogType;
92
+ /** ่ฆ‹ๅ‡บใ— */
93
+ title?: string;
94
+ /** ่กจ็คบใ™ใ‚‹ๆ–‡ๅญ—ๅˆ—ใ€‚้…ๅˆ—ใชใ‚‰1่ฆ็ด ใ‚’1ๆฎต่ฝใจใ—ใฆ่กจ็คบใ™ใ‚‹ */
95
+ message?: string | string[];
96
+ /** true ใฎๅ ดๅˆใ€่ฆ‹ๅ‡บใ—ใจใƒกใƒƒใ‚ปใƒผใ‚ธใ‚’ HTML ใจใ—ใฆ่กจ็คบใ™ใ‚‹ */
97
+ html?: boolean;
98
+ /** ใƒกใƒƒใ‚ปใƒผใ‚ธใฎไธ‹ใซไธฆในใ‚‹็”ปๅƒ */
99
+ image?: ModalDialogImage | ModalDialogImage[];
100
+ /** ๅทฆใ‹ใ‚‰้ †ใซไธฆในใ‚‹ใƒœใ‚ฟใƒณใ€‚ๆœชๆŒ‡ๅฎšใชใ‚‰ confirm ใฏ Yes ใจ Noใ€ใใ‚Œไปฅๅค–ใฏ OK */
101
+ buttons?: ModalDialogButton[];
102
+ /** OK ใƒœใ‚ฟใƒณใฎๆ–‡ๅญ— */
103
+ okLabel?: string;
104
+ /** Yes ใƒœใ‚ฟใƒณใฎๆ–‡ๅญ— */
105
+ yesLabel?: string;
106
+ /** No ใƒœใ‚ฟใƒณใฎๆ–‡ๅญ— */
107
+ noLabel?: string;
108
+ /** Cancel ใƒœใ‚ฟใƒณใฎๆ–‡ๅญ— */
109
+ cancelLabel?: string;
110
+ }
111
+ const props = withDefaults(defineProps<Props>(), {
112
+ type: 'info',
113
+ title: undefined,
114
+ message: undefined,
115
+ html: false,
116
+ image: undefined,
117
+ buttons: undefined,
118
+ okLabel: 'OK',
119
+ yesLabel: 'Yes',
120
+ noLabel: 'No',
121
+ cancelLabel: 'Cancel'
122
+ });
123
+
124
+ export interface Emits {
125
+ /** ใƒœใ‚ฟใƒณใ‹ Esc ใงใƒ€ใ‚คใ‚ขใƒญใ‚ฐใŒ้–‰ใ˜ใŸ */
126
+ (e: 'emit:close', result: ModalDialogResult): void;
127
+ }
128
+ const emit = defineEmits<Emits>();
129
+
130
+ export interface Slots {
131
+ /** ่ฆ‹ๅ‡บใ—ใฎๅทฆใซๅ‡บใ™ใ‚ขใ‚คใ‚ณใƒณ */
132
+ icon?(): unknown;
133
+ /** ใƒกใƒƒใ‚ปใƒผใ‚ธใจ็”ปๅƒใซไปฃใˆใฆ่กจ็คบใ™ใ‚‹ไธญ่บซ */
134
+ default?(): unknown;
135
+ }
136
+ defineSlots<Slots>();
137
+
138
+ /** ่กจ็คบใ™ใ‚‹ใ‹ใ€‚ใƒœใ‚ฟใƒณใ‹ Esc ใง้–‰ใ˜ใ‚‹ใจ false ใซใชใ‚‹ */
139
+ const open = defineModel<boolean>('open', { default: false });
140
+
141
+ const refDialog = ref<HTMLDialogElement>();
142
+ const refButtons = ref<HTMLElement>();
143
+
144
+ const titleId = useId();
145
+ const bodyId = useId();
146
+ const icons = {
147
+ info: SvgInfo,
148
+ confirm: SvgQuestion,
149
+ warn: SvgWarningSign,
150
+ error: SvgCritical
151
+ };
152
+ /** ้–‹ใ„ใŸใจใใซใƒ•ใ‚ฉใƒผใ‚ซใ‚นใ™ใ‚‹ใƒœใ‚ฟใƒณใฎๅ„ชๅ…ˆ้ †ใ€‚ๆ“ไฝœใ‚’ๅ–ใ‚Šๆถˆใ™ๅดใฎใƒœใ‚ฟใƒณใ‚’ๅ„ชๅ…ˆใ™ใ‚‹ */
153
+ const focusOrder: ModalDialogButton[] = ['cancel', 'no', 'yes', 'ok'];
154
+
155
+ const buttons = computed((): ModalDialogButton[] => props.buttons ?? (props.type === 'confirm' ? ['yes', 'no'] : ['ok']));
156
+
157
+ const labels = computed((): Record<ModalDialogButton, string> => ({
158
+ ok: props.okLabel,
159
+ yes: props.yesLabel,
160
+ no: props.noLabel,
161
+ cancel: props.cancelLabel
162
+ }));
163
+
164
+ const messages = computed((): string[] => props.message == null ? [] : [props.message].flat());
165
+
166
+ const images = computed((): Exclude<ModalDialogImage, string>[] => [props.image ?? []].flat().map((image) => {
167
+ if (typeof image === 'string') {
168
+ return {
169
+ src: image,
170
+ alt: ''
171
+ };
172
+ }
173
+ return image;
174
+ }));
175
+
176
+ const onClickButton = (result: ModalDialogResult): void => {
177
+ closeDialog(result);
178
+ };
179
+
180
+ const onCancelDialog = (event: Event): void => {
181
+ event.preventDefault();
182
+ closeDialog('cancel');
183
+ };
184
+
185
+ const onKeydownDialog = (event: KeyboardEvent): void => {
186
+ if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {
187
+ return;
188
+ }
189
+ const elements = [...refButtons.value?.children ?? []] as HTMLElement[];
190
+ const index = elements.indexOf(document.activeElement as HTMLElement);
191
+ if (index < 0) {
192
+ return;
193
+ }
194
+ elements[event.key === 'ArrowRight' ? index + 1 : index - 1]?.focus();
195
+ };
196
+
197
+ const showDialog = (): void => {
198
+ refDialog.value?.showModal();
199
+ const focused = focusOrder.find((button) => buttons.value.includes(button));
200
+ const index = focused ? buttons.value.indexOf(focused) : -1;
201
+ (refButtons.value?.children[index] as HTMLElement | undefined)?.focus();
202
+ };
203
+
204
+ const closeDialog = (result: ModalDialogResult): void => {
205
+ // close ใ‚’ๅ—ใ‘ใฆใ™ใใซใ‚ขใƒณใƒžใ‚ฆใƒณใƒˆใ•ใ‚Œใฆใ‚‚ใ€ใƒ€ใ‚คใ‚ขใƒญใ‚ฐใŒ้–‰ใ˜ใฆใƒ•ใ‚ฉใƒผใ‚ซใ‚นใŒๆˆปใ‚‹ใ‚ˆใ†ๅ…ˆใซ้–‰ใ˜ใ‚‹
206
+ refDialog.value?.close();
207
+ open.value = false;
208
+ emit('emit:close', result);
209
+ };
210
+
211
+ onMounted(() => {
212
+ if (open.value) {
213
+ showDialog();
214
+ }
215
+ });
216
+
217
+ watch(open, (newValue) => {
218
+ if (newValue) {
219
+ showDialog();
220
+ } else {
221
+ refDialog.value?.close();
222
+ }
223
+ }, { flush: 'post' });
224
+ </script>
225
+
226
+ <style>
227
+ :where(.dwui-modal-dialog) {
228
+ box-sizing: border-box;
229
+ width: var(--dwui-width-modal-dialog, 50vw);
230
+ min-width: min(320px, 100%);
231
+ padding: var(--dwui-padding-modal-dialog, 1.67em 2.5em);
232
+ border: 1px solid var(--dwui-border-color-modal-dialog, light-dark(#8f8f8f, #6b6f76));
233
+ border-radius: var(--dwui-radius-modal-dialog, 4px);
234
+ background: var(--dwui-background-modal-dialog, Canvas);
235
+ color: var(--dwui-color-text-modal-dialog, CanvasText);
236
+ box-shadow: var(--dwui-box-shadow-modal-dialog, 0 2px 8px rgba(0, 0, 0, 0.33));
237
+ }
238
+
239
+ :where(.dwui-modal-dialog)::backdrop {
240
+ background: var(--dwui-background-modal-dialog-backdrop, rgba(0, 0, 0, 0.5));
241
+ }
242
+
243
+ :where(.dwui-modal-dialog-header) {
244
+ display: flex;
245
+ align-items: center;
246
+ gap: 0.33em;
247
+ }
248
+
249
+ :where(.dwui-modal-dialog-icon) {
250
+ display: flex;
251
+ flex: none;
252
+ font-size: var(--dwui-font-size-modal-dialog-icon, 1.83em);
253
+ }
254
+
255
+ :where(.dwui-modal-dialog-body) {
256
+ padding: 0.83em;
257
+ overflow-wrap: anywhere;
258
+ }
259
+
260
+ :where(.dwui-modal-dialog-body p) {
261
+ margin: 0;
262
+ white-space: pre-wrap;
263
+ }
264
+
265
+ :where(.dwui-modal-dialog-images) {
266
+ display: flex;
267
+ flex-wrap: wrap;
268
+ gap: 0.33em;
269
+ margin-top: 0.67em;
270
+ }
271
+
272
+ :where(.dwui-modal-dialog-images img) {
273
+ width: var(--dwui-width-modal-dialog-image, 200px);
274
+ max-width: 100%;
275
+ height: auto;
276
+ }
277
+
278
+ :where(.dwui-modal-dialog-buttons) {
279
+ display: flex;
280
+ justify-content: space-evenly;
281
+ padding: 0.83em;
282
+ }
283
+
284
+ :where(.dwui-modal-dialog-button) {
285
+ min-width: var(--dwui-min-width-modal-dialog-button, 80px);
286
+ }
287
+ </style>