@digitalwalletcorp/vue-core 1.2.1 → 1.3.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.
- package/README.md +79 -3
- package/lib/accordion-fieldset.d.cts +14 -4
- package/lib/accordion-fieldset.d.ts +14 -4
- package/lib/accordion-section.d.cts +20 -10
- package/lib/accordion-section.d.ts +20 -10
- package/lib/components-2zQ2SZuY.js +26 -0
- package/lib/components-HaiHcseF.cjs +1 -0
- package/lib/components.d.cts +10 -0
- package/lib/components.d.ts +10 -0
- package/lib/copy-button.d.cts +34 -0
- package/lib/copy-button.d.ts +34 -0
- package/lib/dark-mode-selector.d.cts +32 -0
- package/lib/dark-mode-selector.d.ts +32 -0
- package/lib/data-table.d.cts +30 -0
- package/lib/data-table.d.ts +30 -0
- package/lib/help-button.d.cts +39 -0
- package/lib/help-button.d.ts +39 -0
- package/lib/help-popper.d.cts +39 -0
- package/lib/help-popper.d.ts +39 -0
- package/lib/helpers/data-table-csv.d.cts +17 -0
- package/lib/helpers/data-table-csv.d.ts +17 -0
- package/lib/helpers/show-floating-component.d.cts +82 -0
- package/lib/helpers/show-floating-component.d.ts +82 -0
- package/lib/helpers/show-modal-dialog.d.cts +73 -0
- package/lib/helpers/show-modal-dialog.d.ts +73 -0
- package/lib/helpers/show-overlay-box.d.cts +53 -0
- package/lib/helpers/show-overlay-box.d.ts +53 -0
- package/lib/helpers/show-screen-loading.d.cts +20 -0
- package/lib/helpers/show-screen-loading.d.ts +20 -0
- package/lib/helpers/show-snackbar.d.cts +47 -0
- package/lib/helpers/show-snackbar.d.ts +47 -0
- package/lib/hourglass-loading.d.cts +1 -1
- package/lib/hourglass-loading.d.ts +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.d.cts +34 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.js +445 -18
- package/lib/internal/anchored-popover.d.cts +35 -0
- package/lib/internal/anchored-popover.d.ts +35 -0
- package/lib/internal/anchored-position.d.cts +50 -0
- package/lib/internal/anchored-position.d.ts +50 -0
- package/lib/internal/data-table-controls.d.cts +42 -0
- package/lib/internal/data-table-controls.d.ts +42 -0
- package/lib/internal/data-table-value.d.cts +32 -0
- package/lib/internal/data-table-value.d.ts +32 -0
- package/lib/internal/floating-component.d.cts +52 -0
- package/lib/internal/floating-component.d.ts +52 -0
- package/lib/internal/icon-popper.d.cts +32 -0
- package/lib/internal/icon-popper.d.ts +32 -0
- package/lib/internal/mount-window.d.cts +39 -0
- package/lib/internal/mount-window.d.ts +39 -0
- package/lib/internal/movable-window.d.cts +55 -0
- package/lib/internal/movable-window.d.ts +55 -0
- package/lib/internal/opened-overlay-boxes.d.cts +2 -0
- package/lib/internal/opened-overlay-boxes.d.ts +2 -0
- package/lib/internal/pagination.d.cts +22 -0
- package/lib/internal/pagination.d.ts +22 -0
- package/lib/internal/snackbar-container.d.cts +20 -0
- package/lib/internal/snackbar-container.d.ts +20 -0
- package/lib/internal/snackbar-item.d.cts +17 -0
- package/lib/internal/snackbar-item.d.ts +17 -0
- package/lib/internal/tab-group-context.d.cts +4 -2
- package/lib/internal/tab-group-context.d.ts +4 -2
- package/lib/internal/use-movable-window.d.cts +44 -0
- package/lib/internal/use-movable-window.d.ts +44 -0
- package/lib/internal/window-order.d.cts +6 -0
- package/lib/internal/window-order.d.ts +6 -0
- package/lib/intersection-lazy-component.d.cts +32 -0
- package/lib/intersection-lazy-component.d.ts +32 -0
- package/lib/label-button.d.cts +2 -2
- package/lib/label-button.d.ts +2 -2
- package/lib/label-icon.d.cts +2 -2
- package/lib/label-icon.d.ts +2 -2
- package/lib/modal-dialog.d.cts +67 -0
- package/lib/modal-dialog.d.ts +67 -0
- package/lib/nuxt.cjs +1 -1
- package/lib/nuxt.js +1 -1
- package/lib/overlay-box.d.cts +52 -0
- package/lib/overlay-box.d.ts +52 -0
- package/lib/page-section.d.cts +2 -2
- package/lib/page-section.d.ts +2 -2
- package/lib/page-title.d.cts +2 -2
- package/lib/page-title.d.ts +2 -2
- package/lib/register.cjs +1 -1
- package/lib/register.js +1 -1
- package/lib/screen-loading.d.cts +7 -0
- package/lib/screen-loading.d.ts +7 -0
- package/lib/style.css +1 -1
- package/lib/tab-content.d.cts +5 -5
- package/lib/tab-content.d.ts +5 -5
- package/lib/tab-group.d.cts +7 -10
- package/lib/tab-group.d.ts +7 -10
- package/lib/types/data-table.d.cts +185 -0
- package/lib/types/data-table.d.ts +185 -0
- package/lib/types/modal-dialog.d.cts +13 -0
- package/lib/types/modal-dialog.d.ts +13 -0
- package/lib/types/movable-window.d.cts +16 -0
- package/lib/types/movable-window.d.ts +16 -0
- package/lib/warning-popper.d.cts +39 -0
- package/lib/warning-popper.d.ts +39 -0
- package/lib/warning-popper.vue_vue_type_style_index_0_lang-CxVzqsbn.cjs +1 -0
- package/lib/warning-popper.vue_vue_type_style_index_0_lang-zt-jCsvz.js +1833 -0
- package/package.json +40 -14
- package/src/accordion-fieldset.vue +24 -19
- package/src/accordion-section.vue +33 -28
- package/src/components.ts +10 -0
- package/src/copy-button.vue +89 -0
- package/src/dark-mode-selector.vue +212 -0
- package/src/data-table.vue +643 -0
- package/src/help-button.vue +128 -0
- package/src/help-popper.vue +70 -0
- package/src/helpers/data-table-csv.ts +55 -0
- package/src/helpers/show-floating-component.ts +169 -0
- package/src/helpers/show-modal-dialog.ts +121 -0
- package/src/helpers/show-overlay-box.ts +106 -0
- package/src/helpers/show-screen-loading.ts +37 -0
- package/src/helpers/show-snackbar.ts +153 -0
- package/src/hourglass-loading.vue +1 -1
- package/src/index.ts +34 -0
- package/src/internal/anchored-popover.vue +192 -0
- package/src/internal/anchored-position.ts +135 -0
- package/src/internal/data-table-controls.vue +203 -0
- package/src/internal/data-table-value.ts +99 -0
- package/src/internal/floating-component.vue +202 -0
- package/src/internal/icon-popper.vue +185 -0
- package/src/internal/mount-window.ts +110 -0
- package/src/internal/movable-window.vue +315 -0
- package/src/internal/opened-overlay-boxes.ts +2 -0
- package/src/internal/pagination.vue +325 -0
- package/src/internal/snackbar-container.vue +258 -0
- package/src/internal/snackbar-item.ts +20 -0
- package/src/internal/tab-group-context.ts +4 -2
- package/src/internal/use-movable-window.ts +208 -0
- package/src/internal/window-order.ts +11 -0
- package/src/intersection-lazy-component.vue +84 -0
- package/src/label-button.vue +9 -6
- package/src/label-icon.vue +2 -2
- package/src/modal-dialog.vue +287 -0
- package/src/overlay-box.vue +218 -0
- package/src/page-section.vue +7 -7
- package/src/page-title.vue +4 -4
- package/src/screen-loading.vue +90 -0
- package/src/tab-content.vue +16 -15
- package/src/tab-group.vue +34 -36
- package/src/types/data-table.ts +196 -0
- package/src/types/modal-dialog.ts +16 -0
- package/src/types/movable-window.ts +18 -0
- package/src/warning-popper.vue +70 -0
- package/lib/accordion-fieldset.cjs +0 -1
- package/lib/accordion-fieldset.js +0 -4
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-Cf4czDXz.js +0 -66
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-DoM5QjpJ.cjs +0 -1
- package/lib/accordion-section.cjs +0 -1
- package/lib/accordion-section.js +0 -4
- package/lib/accordion-section.vue_vue_type_style_index_0_lang-CFDdUEnn.cjs +0 -1
- package/lib/accordion-section.vue_vue_type_style_index_0_lang-Gvjjx02P.js +0 -78
- package/lib/components-C63HJoCn.cjs +0 -1
- package/lib/components-q4Cf97bO.js +0 -24
- package/lib/hourglass-loading.cjs +0 -1
- package/lib/hourglass-loading.js +0 -4
- package/lib/hourglass-loading.vue_vue_type_style_index_0_lang-C72UVA9W.cjs +0 -1
- package/lib/hourglass-loading.vue_vue_type_style_index_0_lang-DkUGIxQ2.js +0 -22
- package/lib/label-button.cjs +0 -1
- package/lib/label-button.js +0 -4
- package/lib/label-button.vue_vue_type_style_index_0_lang-D7ZgfZOL.cjs +0 -1
- package/lib/label-button.vue_vue_type_style_index_0_lang-DqRYddVt.js +0 -44
- package/lib/label-icon.cjs +0 -1
- package/lib/label-icon.js +0 -4
- package/lib/label-icon.vue_vue_type_style_index_0_lang-D9Cimu20.cjs +0 -1
- package/lib/label-icon.vue_vue_type_style_index_0_lang-me52HE2V.js +0 -38
- package/lib/page-section.cjs +0 -1
- package/lib/page-section.js +0 -4
- package/lib/page-section.vue_vue_type_style_index_0_lang-DEAkTLxd.cjs +0 -1
- package/lib/page-section.vue_vue_type_style_index_0_lang-DpVQe_rV.js +0 -54
- package/lib/page-title.cjs +0 -1
- package/lib/page-title.js +0 -4
- package/lib/page-title.vue_vue_type_style_index_0_lang-BqIsIks5.cjs +0 -1
- package/lib/page-title.vue_vue_type_style_index_0_lang-ChZot85K.js +0 -36
- package/lib/tab-content.cjs +0 -1
- package/lib/tab-content.js +0 -4
- package/lib/tab-content.vue_vue_type_style_index_0_lang-BeCi7Xkp.cjs +0 -1
- package/lib/tab-content.vue_vue_type_style_index_0_lang-CcQLHmIF.js +0 -44
- package/lib/tab-group.cjs +0 -1
- package/lib/tab-group.js +0 -4
- package/lib/tab-group.vue_vue_type_style_index_0_lang-C84mDEOC.js +0 -103
- package/lib/tab-group.vue_vue_type_style_index_0_lang-CMaufRJV.cjs +0 -1
- package/lib/use-shrinkable-CS2bmsJJ.js +0 -17
- package/lib/use-shrinkable-Cu9JQZll.cjs +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ヘルプボタン
|
|
3
|
+
クリックするとスロットの中身をボタンの近くにポップオーバーで表示する。
|
|
4
|
+
外側のクリック、または Esc で閉じる。
|
|
5
|
+
-->
|
|
6
|
+
<template>
|
|
7
|
+
<button
|
|
8
|
+
ref="refButton"
|
|
9
|
+
type="button"
|
|
10
|
+
class="dwui-help-button"
|
|
11
|
+
:aria-label="props.label"
|
|
12
|
+
v-bind="attrs"
|
|
13
|
+
>
|
|
14
|
+
<slot name="icon">
|
|
15
|
+
<SvgQuestion />
|
|
16
|
+
</slot>
|
|
17
|
+
</button>
|
|
18
|
+
<AnchoredPopover
|
|
19
|
+
ref="refPopover"
|
|
20
|
+
class="dwui-help-button-popover"
|
|
21
|
+
mode="auto"
|
|
22
|
+
:anchor="refButton"
|
|
23
|
+
:placement="props.placement"
|
|
24
|
+
:arrow="props.arrow"
|
|
25
|
+
@emit:open="emit('emit:open')"
|
|
26
|
+
@emit:close="emit('emit:close')"
|
|
27
|
+
>
|
|
28
|
+
<slot />
|
|
29
|
+
</AnchoredPopover>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import { onMounted, ref, useAttrs } from 'vue';
|
|
34
|
+
import { SvgQuestion } from '@digitalwalletcorp/vue-svg-icons';
|
|
35
|
+
import AnchoredPopover from '@/internal/anchored-popover.vue';
|
|
36
|
+
import type { PopoverPlacement } from '@/internal/anchored-position';
|
|
37
|
+
|
|
38
|
+
// ルートが button と パネルの2つなので、属性は button に明示的に渡す
|
|
39
|
+
defineOptions({ inheritAttrs: false });
|
|
40
|
+
|
|
41
|
+
export interface Props {
|
|
42
|
+
/** ボタンに対するパネルの表示位置。収まらないときは反対側に出す */
|
|
43
|
+
placement?: PopoverPlacement;
|
|
44
|
+
/** ボタンを指す矢印をパネルに付ける */
|
|
45
|
+
arrow?: boolean;
|
|
46
|
+
/** ボタンの読み上げ名。aria-label 属性を渡したときはそちらが優先される */
|
|
47
|
+
label?: string;
|
|
48
|
+
}
|
|
49
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
50
|
+
placement: 'bottom-start',
|
|
51
|
+
arrow: false,
|
|
52
|
+
label: 'Help'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export interface Emits {
|
|
56
|
+
(e: 'emit:open'): void;
|
|
57
|
+
(e: 'emit:close'): void;
|
|
58
|
+
}
|
|
59
|
+
const emit = defineEmits<Emits>();
|
|
60
|
+
|
|
61
|
+
export interface Slots {
|
|
62
|
+
/** ボタンのアイコン */
|
|
63
|
+
icon?(): unknown;
|
|
64
|
+
/** パネルに表示する中身 */
|
|
65
|
+
default?(): unknown;
|
|
66
|
+
}
|
|
67
|
+
defineSlots<Slots>();
|
|
68
|
+
|
|
69
|
+
const attrs = useAttrs();
|
|
70
|
+
|
|
71
|
+
const refButton = ref<HTMLButtonElement>();
|
|
72
|
+
const refPopover = ref<InstanceType<typeof AnchoredPopover>>();
|
|
73
|
+
|
|
74
|
+
onMounted(() => {
|
|
75
|
+
// ボタンをパネルの invoker にする。クリックでの開閉、外側クリックの判定、Esc で閉じた後のフォーカスの戻りをブラウザに任せる
|
|
76
|
+
const panel = refPopover.value?.element;
|
|
77
|
+
if (refButton.value && panel) {
|
|
78
|
+
refButton.value.popoverTargetElement = panel;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style>
|
|
84
|
+
:where(.dwui-help-button) {
|
|
85
|
+
display: inline-flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
vertical-align: middle;
|
|
89
|
+
padding: 0.17em;
|
|
90
|
+
border: none;
|
|
91
|
+
border-radius: 4px;
|
|
92
|
+
background-color: transparent;
|
|
93
|
+
background-image: none;
|
|
94
|
+
color: inherit;
|
|
95
|
+
font: inherit;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
:where(.dwui-help-button:not(:disabled):hover) {
|
|
100
|
+
background: var(--dwui-background-help-button-hover, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.12)));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:where(.dwui-help-button:not(:disabled):active) {
|
|
104
|
+
transform: translate(1px, 1px);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where(.dwui-help-button:disabled) {
|
|
108
|
+
opacity: 0.4;
|
|
109
|
+
cursor: not-allowed;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
:where(.dwui-help-button:focus-visible) {
|
|
113
|
+
outline: var(--dwui-outline-width-focus-ring, 2px) solid var(--dwui-outline-color-focus-ring, Highlight);
|
|
114
|
+
outline-offset: var(--dwui-outline-offset-focus-ring, 2px);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
:where(.dwui-help-button-popover) {
|
|
118
|
+
--dwui-max-width-anchored-popover: var(--dwui-max-width-help-button-popover, calc(100vw - 16px));
|
|
119
|
+
--dwui-max-height-anchored-popover: var(--dwui-max-height-help-button-popover, calc(100vh - 16px));
|
|
120
|
+
--dwui-padding-anchored-popover: var(--dwui-padding-help-button-popover, 0.67em 1em);
|
|
121
|
+
--dwui-border-color-anchored-popover: var(--dwui-border-color-help-button-popover, light-dark(#8f8f8f, #6b6f76));
|
|
122
|
+
--dwui-radius-anchored-popover: var(--dwui-radius-help-button-popover, 4px);
|
|
123
|
+
--dwui-background-anchored-popover: var(--dwui-background-help-button-popover, Canvas);
|
|
124
|
+
--dwui-background-anchored-popover-arrow: var(--dwui-background-help-button-popover-arrow, var(--dwui-background-help-button-popover, Canvas));
|
|
125
|
+
--dwui-color-text-anchored-popover: var(--dwui-color-text-help-button-popover, CanvasText);
|
|
126
|
+
--dwui-box-shadow-anchored-popover: var(--dwui-box-shadow-help-button-popover, 0 2px 8px rgba(0, 0, 0, 0.25));
|
|
127
|
+
}
|
|
128
|
+
</style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ヘルプポップアップ
|
|
3
|
+
アイコンにマウスを載せている、またはフォーカスしている間だけ補足説明を表示する。
|
|
4
|
+
-->
|
|
5
|
+
<template>
|
|
6
|
+
<IconPopper
|
|
7
|
+
class="dwui-help-popper"
|
|
8
|
+
popover-class="dwui-help-popper-popover"
|
|
9
|
+
:placement="props.placement"
|
|
10
|
+
:arrow="props.arrow"
|
|
11
|
+
:label="props.label"
|
|
12
|
+
@emit:open="emit('emit:open')"
|
|
13
|
+
@emit:close="emit('emit:close')"
|
|
14
|
+
>
|
|
15
|
+
<template #icon>
|
|
16
|
+
<slot name="icon">
|
|
17
|
+
<SvgQuestion />
|
|
18
|
+
</slot>
|
|
19
|
+
</template>
|
|
20
|
+
<slot />
|
|
21
|
+
</IconPopper>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup lang="ts">
|
|
25
|
+
import { SvgQuestion } from '@digitalwalletcorp/vue-svg-icons';
|
|
26
|
+
import IconPopper from '@/internal/icon-popper.vue';
|
|
27
|
+
import type { PopoverPlacement } from '@/internal/anchored-position';
|
|
28
|
+
|
|
29
|
+
export interface Props {
|
|
30
|
+
/** アイコンに対するパネルの表示位置。収まらないときは反対側に出す */
|
|
31
|
+
placement?: PopoverPlacement;
|
|
32
|
+
/** アイコンを指す矢印をパネルに付ける */
|
|
33
|
+
arrow?: boolean;
|
|
34
|
+
/** アイコンの読み上げ名 */
|
|
35
|
+
label?: string;
|
|
36
|
+
}
|
|
37
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
38
|
+
placement: 'right',
|
|
39
|
+
arrow: true,
|
|
40
|
+
label: 'Help'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export interface Emits {
|
|
44
|
+
(e: 'emit:open'): void;
|
|
45
|
+
(e: 'emit:close'): void;
|
|
46
|
+
}
|
|
47
|
+
const emit = defineEmits<Emits>();
|
|
48
|
+
|
|
49
|
+
export interface Slots {
|
|
50
|
+
/** アイコン */
|
|
51
|
+
icon?(): unknown;
|
|
52
|
+
/** パネルに表示する中身 */
|
|
53
|
+
default?(): unknown;
|
|
54
|
+
}
|
|
55
|
+
defineSlots<Slots>();
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style>
|
|
59
|
+
:where(.dwui-help-popper-popover) {
|
|
60
|
+
--dwui-max-width-anchored-popover: var(--dwui-max-width-help-popper, calc(100vw - 16px));
|
|
61
|
+
--dwui-max-height-anchored-popover: var(--dwui-max-height-help-popper, calc(100vh - 16px));
|
|
62
|
+
--dwui-padding-anchored-popover: var(--dwui-padding-help-popper, 0.67em 1em);
|
|
63
|
+
--dwui-border-color-anchored-popover: var(--dwui-border-color-help-popper, light-dark(#8f8f8f, #6b6f76));
|
|
64
|
+
--dwui-radius-anchored-popover: var(--dwui-radius-help-popper, 4px);
|
|
65
|
+
--dwui-background-anchored-popover: var(--dwui-background-help-popper, Canvas);
|
|
66
|
+
--dwui-background-anchored-popover-arrow: var(--dwui-background-help-popper-arrow, var(--dwui-background-help-popper, Canvas));
|
|
67
|
+
--dwui-color-text-anchored-popover: var(--dwui-color-text-help-popper, CanvasText);
|
|
68
|
+
--dwui-box-shadow-anchored-popover: var(--dwui-box-shadow-help-popper, 0 2px 8px rgba(0, 0, 0, 0.25));
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getValueByPath, resolveLabel } from '@/internal/data-table-value';
|
|
2
|
+
import type { DataTableCsvColumn, DataTableHeader } from '@/types/data-table';
|
|
3
|
+
|
|
4
|
+
/** 行番号を出力するキー */
|
|
5
|
+
const INDEX_KEY = '$index';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* ヘッダから CSV に出力する列の定義を取り出す。csv を持たないヘッダと disabled の列は含めない
|
|
9
|
+
*/
|
|
10
|
+
const toCsvColumns = <T>(headers: DataTableHeader<T>[]): { header: DataTableHeader<T>; column: DataTableCsvColumn<T> }[] => {
|
|
11
|
+
const columns: { header: DataTableHeader<T>; column: DataTableCsvColumn<T> }[] = [];
|
|
12
|
+
for (const header of headers) {
|
|
13
|
+
if (header.csv === true) {
|
|
14
|
+
columns.push({ header, column: {} });
|
|
15
|
+
} else if (Array.isArray(header.csv)) {
|
|
16
|
+
for (const column of header.csv) {
|
|
17
|
+
if (!column.disabled) {
|
|
18
|
+
columns.push({ header, column });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return columns;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* ヘッダの csv の定義から CSV の列名を作る
|
|
28
|
+
*
|
|
29
|
+
* @param {DataTableHeader<T>[]} headers
|
|
30
|
+
* @returns {string[]} 列名
|
|
31
|
+
*/
|
|
32
|
+
export const headersToCsvColumns = <T>(headers: DataTableHeader<T>[]): string[] => {
|
|
33
|
+
return toCsvColumns(headers).map(({ header, column }) => resolveLabel(column.label ?? header.label));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ヘッダの csv の定義に従って行から CSV の列の値を取り出す
|
|
38
|
+
*
|
|
39
|
+
* @param {DataTableHeader<T>[]} headers
|
|
40
|
+
* @param {T} row
|
|
41
|
+
* @param {number} [rowNumber] key が '$index' の列に出力する行番号
|
|
42
|
+
* @returns {unknown[]} 列の値。文字列化はしない
|
|
43
|
+
*/
|
|
44
|
+
export const rowToCsvColumns = <T>(headers: DataTableHeader<T>[], row: T, rowNumber?: number): unknown[] => {
|
|
45
|
+
return toCsvColumns(headers).map(({ header, column }) => {
|
|
46
|
+
if (column.format) {
|
|
47
|
+
return column.format(row);
|
|
48
|
+
}
|
|
49
|
+
const key = column.key ?? header.id;
|
|
50
|
+
if (key === INDEX_KEY) {
|
|
51
|
+
return rowNumber;
|
|
52
|
+
}
|
|
53
|
+
return getValueByPath(row, key);
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { h } from 'vue';
|
|
2
|
+
import type { AppContext, ClassValue, Component, StyleValue, VNode } from 'vue';
|
|
3
|
+
import FloatingComponent from '@/internal/floating-component.vue';
|
|
4
|
+
import { mountWindow, useWindowOwner } from '@/internal/mount-window';
|
|
5
|
+
import type { MovableWindowContentProps, MovableWindowDragMode, MovableWindowHandle } from '@/types/movable-window';
|
|
6
|
+
|
|
7
|
+
/** showFloatingComponent が中身のコンポーネントに props として渡す関数 */
|
|
8
|
+
export type FloatingComponentContentProps = MovableWindowContentProps;
|
|
9
|
+
|
|
10
|
+
/** showFloatingComponent / showFloatingMessage が返す、表示中のウィンドウを操作するためのハンドル */
|
|
11
|
+
export type FloatingComponentHandle = MovableWindowHandle;
|
|
12
|
+
|
|
13
|
+
export interface ShowFloatingComponentOptions {
|
|
14
|
+
/** 見出し */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** この要素の下に開く。下に収まらなければ上に開く。未指定ならページの表示中の左上に開く */
|
|
17
|
+
anchor?: HTMLElement;
|
|
18
|
+
/** ドラッグで移動するときに掴む範囲 */
|
|
19
|
+
dragMode?: MovableWindowDragMode;
|
|
20
|
+
/** 閉じるボタンの読み上げ名 */
|
|
21
|
+
closeLabel?: string;
|
|
22
|
+
/** 見出しにコピーボタンを置き、この値をコピーする。関数を渡すとクリック時に呼び出して値を得る */
|
|
23
|
+
copyValue?: string | number | (() => string | number);
|
|
24
|
+
/** コピーボタンの読み上げ名 */
|
|
25
|
+
copyLabel?: string;
|
|
26
|
+
/** ウィンドウのダブルクリックで閉じる */
|
|
27
|
+
closeOnDblClick?: boolean;
|
|
28
|
+
/** 開いている間、背面のページをスクロールさせない */
|
|
29
|
+
lockScroll?: boolean;
|
|
30
|
+
/** 初期の幅・高さ(px) */
|
|
31
|
+
initialSize?: {
|
|
32
|
+
width?: number;
|
|
33
|
+
height?: number;
|
|
34
|
+
};
|
|
35
|
+
/** ウィンドウに付けるクラス */
|
|
36
|
+
class?: ClassValue;
|
|
37
|
+
/** ウィンドウに付けるスタイル */
|
|
38
|
+
style?: StyleValue;
|
|
39
|
+
/** 見出しに付けるクラス */
|
|
40
|
+
headerClass?: ClassValue;
|
|
41
|
+
/** 見出しに付けるスタイル */
|
|
42
|
+
headerStyle?: StyleValue;
|
|
43
|
+
/**
|
|
44
|
+
* 中身のコンポーネントに引き継ぐアプリのコンテキスト。
|
|
45
|
+
* 中身でアプリに登録したプラグイン・コンポーネント・provide を使う場合に渡す
|
|
46
|
+
*/
|
|
47
|
+
appContext?: AppContext;
|
|
48
|
+
/** ウィンドウが閉じ終わって取り外されたときに呼ぶ関数。ハンドル・利用者の操作・closeAllFloatingComponents のどれで閉じても呼ぶ */
|
|
49
|
+
onClose?: () => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const openedHandles = new Set<FloatingComponentHandle>();
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* FloatingComponent を body の末尾に描画する
|
|
56
|
+
*
|
|
57
|
+
* @param {(content: FloatingComponentContentProps) => VNode} renderContent 中身を描画する関数
|
|
58
|
+
* @param {ShowFloatingComponentOptions} [options]
|
|
59
|
+
* @param {() => void} [onClosed] 閉じ終わったときに呼ぶ関数
|
|
60
|
+
* @returns {FloatingComponentHandle}
|
|
61
|
+
*/
|
|
62
|
+
const mountFloatingComponent = (
|
|
63
|
+
renderContent: (content: FloatingComponentContentProps) => VNode,
|
|
64
|
+
options?: ShowFloatingComponentOptions,
|
|
65
|
+
onClosed?: () => void
|
|
66
|
+
): FloatingComponentHandle => {
|
|
67
|
+
const { appContext, onClose, ...windowProps } = options ?? {};
|
|
68
|
+
return mountWindow((stateProps, handle) => h(FloatingComponent, {
|
|
69
|
+
closeLabel: 'Close',
|
|
70
|
+
copyLabel: 'Copy',
|
|
71
|
+
closeOnDblClick: false,
|
|
72
|
+
lockScroll: false,
|
|
73
|
+
...windowProps,
|
|
74
|
+
...stateProps
|
|
75
|
+
}, {
|
|
76
|
+
default: () => renderContent(handle)
|
|
77
|
+
}), { appContext, onClose, onClosed }, openedHandles);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const renderComponent = (component: Component, props?: Record<string, unknown>) => (content: FloatingComponentContentProps): VNode => {
|
|
81
|
+
return h(component, {
|
|
82
|
+
...props,
|
|
83
|
+
...content
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const toMessageText = (message: string | object): string => {
|
|
88
|
+
return typeof message === 'string' ? message : JSON.stringify(message, null, 2);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const renderMessage = (text: string) => (): VNode => {
|
|
92
|
+
return h('div', { class: 'dwui-floating-component-message' }, text);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* FloatingComponent を body の末尾に描画し、中身にコンポーネントを表示する。
|
|
97
|
+
* 中身のコンポーネントには、渡した props に加えて close と setLoading を props として渡す。
|
|
98
|
+
* ブラウザでのみ動作する
|
|
99
|
+
*
|
|
100
|
+
* @param {Component} component 中身に表示するコンポーネント
|
|
101
|
+
* @param {Record<string, unknown>} [props] 中身のコンポーネントに渡す props
|
|
102
|
+
* @param {ShowFloatingComponentOptions} [options]
|
|
103
|
+
* @returns {FloatingComponentHandle}
|
|
104
|
+
*/
|
|
105
|
+
export function showFloatingComponent(component: Component, props?: Record<string, unknown>, options?: ShowFloatingComponentOptions): FloatingComponentHandle {
|
|
106
|
+
return mountFloatingComponent(renderComponent(component, props), options);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* FloatingComponent を body の末尾に描画し、中身に文字列を表示する。
|
|
111
|
+
* 文字列は HTML として解釈せず、改行や空白をそのまま表示する。オブジェクトは整形した JSON で表示する。
|
|
112
|
+
* 見出しのコピーボタンは、copyValue を指定しなければ表示した文字列をコピーする。
|
|
113
|
+
* ブラウザでのみ動作する
|
|
114
|
+
*
|
|
115
|
+
* @param {string | object} message 表示する文字列またはオブジェクト
|
|
116
|
+
* @param {ShowFloatingComponentOptions} [options]
|
|
117
|
+
* @returns {FloatingComponentHandle}
|
|
118
|
+
*/
|
|
119
|
+
export function showFloatingMessage(message: string | object, options?: ShowFloatingComponentOptions): FloatingComponentHandle {
|
|
120
|
+
const text = toMessageText(message);
|
|
121
|
+
return mountFloatingComponent(renderMessage(text), {
|
|
122
|
+
copyValue: text,
|
|
123
|
+
...options
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 開いている FloatingComponent をすべて閉じる
|
|
129
|
+
*/
|
|
130
|
+
export function closeAllFloatingComponents(): void {
|
|
131
|
+
for (const handle of [...openedHandles]) {
|
|
132
|
+
handle.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 呼び出したコンポーネントに結び付けて FloatingComponent を開く関数を返す。
|
|
138
|
+
* 開いたウィンドウは、呼び出したコンポーネントがアンマウントされると閉じる。
|
|
139
|
+
* appContext を指定しなければ、呼び出したコンポーネントのアプリのコンテキストを中身に引き継ぐ。
|
|
140
|
+
* コンポーネントの setup の中で呼ぶこと
|
|
141
|
+
*
|
|
142
|
+
* @returns {{ showFloatingComponent: typeof showFloatingComponent; showFloatingMessage: typeof showFloatingMessage }}
|
|
143
|
+
*/
|
|
144
|
+
export function useFloatingComponent(): {
|
|
145
|
+
showFloatingComponent: typeof showFloatingComponent;
|
|
146
|
+
showFloatingMessage: typeof showFloatingMessage;
|
|
147
|
+
} {
|
|
148
|
+
const owner = useWindowOwner('useFloatingComponent');
|
|
149
|
+
|
|
150
|
+
const withOwner = (options?: ShowFloatingComponentOptions): ShowFloatingComponentOptions => {
|
|
151
|
+
return {
|
|
152
|
+
appContext: owner.appContext,
|
|
153
|
+
...options
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
showFloatingComponent: (component, props, options) => {
|
|
159
|
+
return owner.own((onClosed) => mountFloatingComponent(renderComponent(component, props), withOwner(options), onClosed));
|
|
160
|
+
},
|
|
161
|
+
showFloatingMessage: (message, options) => {
|
|
162
|
+
const text = toMessageText(message);
|
|
163
|
+
return owner.own((onClosed) => mountFloatingComponent(renderMessage(text), withOwner({
|
|
164
|
+
copyValue: text,
|
|
165
|
+
...options
|
|
166
|
+
}), onClosed));
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { h, render } from 'vue';
|
|
2
|
+
import type { AppContext, ClassValue, Component, StyleValue } from 'vue';
|
|
3
|
+
import ModalDialog from '@/modal-dialog.vue';
|
|
4
|
+
import type { ModalDialogButton, ModalDialogImage, ModalDialogResult, ModalDialogType } from '@/types/modal-dialog';
|
|
5
|
+
|
|
6
|
+
export interface ShowModalDialogOptions {
|
|
7
|
+
/** ダイアログの種類 */
|
|
8
|
+
type?: ModalDialogType;
|
|
9
|
+
/** 見出し */
|
|
10
|
+
title?: string;
|
|
11
|
+
/** true の場合、見出しとメッセージを HTML として表示する */
|
|
12
|
+
html?: boolean;
|
|
13
|
+
/** メッセージの下に並べる画像 */
|
|
14
|
+
image?: ModalDialogImage | ModalDialogImage[];
|
|
15
|
+
/** 種類ごとのアイコンに代えて表示するコンポーネント */
|
|
16
|
+
icon?: Component;
|
|
17
|
+
/** 左から順に並べるボタン。未指定なら confirm は Yes と No、それ以外は OK */
|
|
18
|
+
buttons?: ModalDialogButton[];
|
|
19
|
+
/** OK ボタンの文字 */
|
|
20
|
+
okLabel?: string;
|
|
21
|
+
/** Yes ボタンの文字 */
|
|
22
|
+
yesLabel?: string;
|
|
23
|
+
/** No ボタンの文字 */
|
|
24
|
+
noLabel?: string;
|
|
25
|
+
/** Cancel ボタンの文字 */
|
|
26
|
+
cancelLabel?: string;
|
|
27
|
+
/** ダイアログに付けるクラス */
|
|
28
|
+
class?: ClassValue;
|
|
29
|
+
/** ダイアログに付けるスタイル */
|
|
30
|
+
style?: StyleValue;
|
|
31
|
+
/**
|
|
32
|
+
* icon のコンポーネントに引き継ぐアプリのコンテキスト。
|
|
33
|
+
* icon でアプリに登録したプラグイン・コンポーネント・provide を使う場合に渡す
|
|
34
|
+
*/
|
|
35
|
+
appContext?: AppContext;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* ModalDialog を body の末尾に描画して開き、閉じたら取り外す。ブラウザでのみ動作する
|
|
40
|
+
*
|
|
41
|
+
* @param {string | string[]} message 表示する文字列。配列なら1要素を1段落として表示する
|
|
42
|
+
* @param {ShowModalDialogOptions} [options]
|
|
43
|
+
* @returns {Promise<ModalDialogResult>} 閉じたボタン
|
|
44
|
+
*/
|
|
45
|
+
export function showModalDialog(message: string | string[], options?: ShowModalDialogOptions): Promise<ModalDialogResult> {
|
|
46
|
+
const { icon, appContext, ...dialogProps } = options ?? {};
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const container = document.createElement('div');
|
|
49
|
+
document.body.appendChild(container);
|
|
50
|
+
const vnode = h(ModalDialog, {
|
|
51
|
+
...dialogProps,
|
|
52
|
+
message,
|
|
53
|
+
open: true,
|
|
54
|
+
'onEmit:close': (result: ModalDialogResult) => {
|
|
55
|
+
render(null, container);
|
|
56
|
+
container.remove();
|
|
57
|
+
resolve(result);
|
|
58
|
+
}
|
|
59
|
+
}, icon ? { icon: () => h(icon) } : undefined);
|
|
60
|
+
if (appContext) {
|
|
61
|
+
vnode.appContext = appContext;
|
|
62
|
+
}
|
|
63
|
+
render(vnode, container);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 情報を伝えるダイアログを開く
|
|
69
|
+
*
|
|
70
|
+
* @param {string | string[]} message 表示する文字列
|
|
71
|
+
* @param {Omit<ShowModalDialogOptions, 'type'>} [options]
|
|
72
|
+
* @returns {Promise<ModalDialogResult>} 閉じたボタン
|
|
73
|
+
*/
|
|
74
|
+
export function showInformationDialog(message: string | string[], options?: Omit<ShowModalDialogOptions, 'type'>): Promise<ModalDialogResult> {
|
|
75
|
+
return showModalDialog(message, {
|
|
76
|
+
...options,
|
|
77
|
+
type: 'info'
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Yes / No を尋ねるダイアログを開く
|
|
83
|
+
*
|
|
84
|
+
* @param {string | string[]} message 表示する文字列
|
|
85
|
+
* @param {Omit<ShowModalDialogOptions, 'type'>} [options]
|
|
86
|
+
* @returns {Promise<ModalDialogResult>} 閉じたボタン
|
|
87
|
+
*/
|
|
88
|
+
export function showConfirmationDialog(message: string | string[], options?: Omit<ShowModalDialogOptions, 'type'>): Promise<ModalDialogResult> {
|
|
89
|
+
return showModalDialog(message, {
|
|
90
|
+
...options,
|
|
91
|
+
type: 'confirm'
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 警告のダイアログを開く
|
|
97
|
+
*
|
|
98
|
+
* @param {string | string[]} message 表示する文字列
|
|
99
|
+
* @param {Omit<ShowModalDialogOptions, 'type'>} [options]
|
|
100
|
+
* @returns {Promise<ModalDialogResult>} 閉じたボタン
|
|
101
|
+
*/
|
|
102
|
+
export function showWarningDialog(message: string | string[], options?: Omit<ShowModalDialogOptions, 'type'>): Promise<ModalDialogResult> {
|
|
103
|
+
return showModalDialog(message, {
|
|
104
|
+
...options,
|
|
105
|
+
type: 'warn'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* エラーのダイアログを開く
|
|
111
|
+
*
|
|
112
|
+
* @param {string | string[]} message 表示する文字列
|
|
113
|
+
* @param {Omit<ShowModalDialogOptions, 'type'>} [options]
|
|
114
|
+
* @returns {Promise<ModalDialogResult>} 閉じたボタン
|
|
115
|
+
*/
|
|
116
|
+
export function showErrorDialog(message: string | string[], options?: Omit<ShowModalDialogOptions, 'type'>): Promise<ModalDialogResult> {
|
|
117
|
+
return showModalDialog(message, {
|
|
118
|
+
...options,
|
|
119
|
+
type: 'error'
|
|
120
|
+
});
|
|
121
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { h } from 'vue';
|
|
2
|
+
import type { AppContext, ClassValue, Component, StyleValue } from 'vue';
|
|
3
|
+
import OverlayBox from '@/overlay-box.vue';
|
|
4
|
+
import { mountWindow, useWindowOwner } from '@/internal/mount-window';
|
|
5
|
+
import type { MovableWindowContentProps, MovableWindowDragMode, MovableWindowHandle } from '@/types/movable-window';
|
|
6
|
+
|
|
7
|
+
/** showOverlayBox が中身のコンポーネントに props として渡す関数 */
|
|
8
|
+
export type OverlayBoxContentProps = MovableWindowContentProps;
|
|
9
|
+
|
|
10
|
+
/** showOverlayBox が返す、表示中のボックスを操作するためのハンドル */
|
|
11
|
+
export type OverlayBoxHandle = MovableWindowHandle;
|
|
12
|
+
|
|
13
|
+
export interface ShowOverlayBoxOptions {
|
|
14
|
+
/** 見出し */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** ドラッグで移動するときに掴む範囲 */
|
|
17
|
+
dragMode?: MovableWindowDragMode;
|
|
18
|
+
/** 暗幕のクリックで閉じる */
|
|
19
|
+
closeOnBackdrop?: boolean;
|
|
20
|
+
/** 閉じるボタンの読み上げ名 */
|
|
21
|
+
closeLabel?: string;
|
|
22
|
+
/** ボックスのルート要素に付けるクラス */
|
|
23
|
+
class?: ClassValue;
|
|
24
|
+
/** ボックスのルート要素に付けるスタイル */
|
|
25
|
+
style?: StyleValue;
|
|
26
|
+
/**
|
|
27
|
+
* 中身のコンポーネントに引き継ぐアプリのコンテキスト。
|
|
28
|
+
* 中身でアプリに登録したプラグイン・コンポーネント・provide を使う場合に渡す
|
|
29
|
+
*/
|
|
30
|
+
appContext?: AppContext;
|
|
31
|
+
/** ボックスが閉じ終わって取り外されたときに呼ぶ関数。ハンドル・利用者の操作・closeAllOverlayBoxes のどれで閉じても呼ぶ */
|
|
32
|
+
onClose?: () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const openedHandles = new Set<OverlayBoxHandle>();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* OverlayBox を body の末尾に描画し、中身にコンポーネントを表示する
|
|
39
|
+
*
|
|
40
|
+
* @param {Component} component 中身に表示するコンポーネント
|
|
41
|
+
* @param {Record<string, unknown>} [props] 中身のコンポーネントに渡す props
|
|
42
|
+
* @param {ShowOverlayBoxOptions} [options]
|
|
43
|
+
* @param {() => void} [onClosed] 閉じ終わったときに呼ぶ関数
|
|
44
|
+
* @returns {OverlayBoxHandle}
|
|
45
|
+
*/
|
|
46
|
+
const mountOverlayBox = (
|
|
47
|
+
component: Component,
|
|
48
|
+
props?: Record<string, unknown>,
|
|
49
|
+
options?: ShowOverlayBoxOptions,
|
|
50
|
+
onClosed?: () => void
|
|
51
|
+
): OverlayBoxHandle => {
|
|
52
|
+
const { appContext, onClose, ...boxProps } = options ?? {};
|
|
53
|
+
return mountWindow((windowProps, handle) => h(OverlayBox, {
|
|
54
|
+
...boxProps,
|
|
55
|
+
...windowProps
|
|
56
|
+
}, {
|
|
57
|
+
default: () => h(component, {
|
|
58
|
+
...props,
|
|
59
|
+
close: handle.close,
|
|
60
|
+
setLoading: handle.setLoading
|
|
61
|
+
})
|
|
62
|
+
}), { appContext, onClose, onClosed }, openedHandles);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* OverlayBox を body の末尾に描画し、中身にコンポーネントを表示する。
|
|
67
|
+
* 中身のコンポーネントには、渡した props に加えて close と setLoading を props として渡す。
|
|
68
|
+
* テンプレートに置けない処理(ボタンのクリックで画面を開くなど)から呼ぶためのもので、ブラウザでのみ動作する
|
|
69
|
+
*
|
|
70
|
+
* @param {Component} component 中身に表示するコンポーネント
|
|
71
|
+
* @param {Record<string, unknown>} [props] 中身のコンポーネントに渡す props
|
|
72
|
+
* @param {ShowOverlayBoxOptions} [options]
|
|
73
|
+
* @returns {OverlayBoxHandle}
|
|
74
|
+
*/
|
|
75
|
+
export function showOverlayBox(component: Component, props?: Record<string, unknown>, options?: ShowOverlayBoxOptions): OverlayBoxHandle {
|
|
76
|
+
return mountOverlayBox(component, props, options);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 開いている OverlayBox をすべて閉じる
|
|
81
|
+
*/
|
|
82
|
+
export function closeAllOverlayBoxes(): void {
|
|
83
|
+
for (const handle of [...openedHandles]) {
|
|
84
|
+
handle.close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 呼び出したコンポーネントに結び付けて OverlayBox を開く関数を返す。
|
|
90
|
+
* 開いたボックスは、呼び出したコンポーネントがアンマウントされると閉じる。
|
|
91
|
+
* appContext を指定しなければ、呼び出したコンポーネントのアプリのコンテキストを中身に引き継ぐ。
|
|
92
|
+
* コンポーネントの setup の中で呼ぶこと
|
|
93
|
+
*
|
|
94
|
+
* @returns {{ showOverlayBox: typeof showOverlayBox }}
|
|
95
|
+
*/
|
|
96
|
+
export function useOverlayBox(): { showOverlayBox: typeof showOverlayBox } {
|
|
97
|
+
const owner = useWindowOwner('useOverlayBox');
|
|
98
|
+
return {
|
|
99
|
+
showOverlayBox: (component, props, options) => {
|
|
100
|
+
return owner.own((onClosed) => mountOverlayBox(component, props, {
|
|
101
|
+
appContext: owner.appContext,
|
|
102
|
+
...options
|
|
103
|
+
}, onClosed));
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { h, render } from 'vue';
|
|
2
|
+
import type { ClassValue, StyleValue } from 'vue';
|
|
3
|
+
import ScreenLoading from '@/screen-loading.vue';
|
|
4
|
+
|
|
5
|
+
export interface ShowScreenLoadingOptions {
|
|
6
|
+
/** ローディングのルート要素に付けるクラス */
|
|
7
|
+
class?: ClassValue;
|
|
8
|
+
/** ローディングのルート要素に付けるスタイル */
|
|
9
|
+
style?: StyleValue;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** showScreenLoading が返す、表示中のローディングを閉じるためのハンドル */
|
|
13
|
+
export interface ScreenLoadingHandle {
|
|
14
|
+
/** ローディングを閉じて取り外す */
|
|
15
|
+
close: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* ScreenLoading を body の末尾に描画して表示する。
|
|
20
|
+
* テンプレートに置けない処理(API 呼び出しの前後など)から呼ぶためのもので、ブラウザでのみ動作する
|
|
21
|
+
*
|
|
22
|
+
* @param {ShowScreenLoadingOptions} [options]
|
|
23
|
+
* @returns {ScreenLoadingHandle}
|
|
24
|
+
*/
|
|
25
|
+
export function showScreenLoading(options?: ShowScreenLoadingOptions): ScreenLoadingHandle {
|
|
26
|
+
const container = document.createElement('div');
|
|
27
|
+
document.body.appendChild(container);
|
|
28
|
+
const close = () => {
|
|
29
|
+
render(null, container);
|
|
30
|
+
container.remove();
|
|
31
|
+
};
|
|
32
|
+
render(h(ScreenLoading, {
|
|
33
|
+
...options,
|
|
34
|
+
loading: true
|
|
35
|
+
}), container);
|
|
36
|
+
return { close };
|
|
37
|
+
}
|