@digitalwalletcorp/vue-core 1.2.0 → 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 +95 -8
- 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 +43 -16
- package/src/accordion-fieldset.vue +29 -19
- package/src/accordion-section.vue +41 -26
- 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 +37 -3
- 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 +5 -5
- package/src/screen-loading.vue +90 -0
- package/src/tab-content.vue +17 -16
- package/src/tab-group.vue +55 -46
- 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-n-IZxUiu.js +0 -66
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-t9NqmoZW.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-CNOeuZPu.cjs +0 -1
- package/lib/components-DBK8NUBh.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_script_setup_true_lang-BwVOxaJP.cjs +0 -1
- package/lib/label-button.vue_vue_type_script_setup_true_lang-DorC4pKz.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,218 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
オーバーレイボックス
|
|
3
|
+
画面全体に暗幕を掛け、その上に見出しと閉じるボタンの付いたウィンドウを表示する。
|
|
4
|
+
閉じるボタン・Esc・暗幕のクリック(closeOnBackdrop)で閉じる。ウィンドウはドラッグで移動でき、右下のつまみでリサイズできる。
|
|
5
|
+
中に置いた要素が body 直下に描画するツールチップやドロップダウンを隠さないよう、<dialog> の最前面表示ではなく z-index で前面に出す。
|
|
6
|
+
FloatingComponent とは開いた順に重なり、後から開いたものが前面に出る。
|
|
7
|
+
-->
|
|
8
|
+
<template>
|
|
9
|
+
<Transition
|
|
10
|
+
name="dwui-overlay-box-fade"
|
|
11
|
+
@after-leave="onAfterLeaveOverlayBox"
|
|
12
|
+
>
|
|
13
|
+
<div
|
|
14
|
+
v-if="open"
|
|
15
|
+
class="dwui-overlay-box"
|
|
16
|
+
:style="{ '--dwui-order-window': order }"
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="dwui-overlay-box-backdrop"
|
|
20
|
+
@click="onClickBackdrop"
|
|
21
|
+
/>
|
|
22
|
+
<MovableWindow
|
|
23
|
+
ref="refWindow"
|
|
24
|
+
class="dwui-overlay-box-container"
|
|
25
|
+
name="dwui-overlay-box"
|
|
26
|
+
tabindex="-1"
|
|
27
|
+
:drag-mode="props.dragMode"
|
|
28
|
+
:loading="props.loading"
|
|
29
|
+
:close-label="props.closeLabel"
|
|
30
|
+
clamp-bottom
|
|
31
|
+
@keydown="onKeydownWindow"
|
|
32
|
+
@emit:close="onCloseWindow"
|
|
33
|
+
>
|
|
34
|
+
<template #title>
|
|
35
|
+
<slot name="title">
|
|
36
|
+
{{ props.title }}
|
|
37
|
+
</slot>
|
|
38
|
+
</template>
|
|
39
|
+
<slot />
|
|
40
|
+
</MovableWindow>
|
|
41
|
+
</div>
|
|
42
|
+
</Transition>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<script setup lang="ts">
|
|
46
|
+
import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
47
|
+
import MovableWindow from '@/internal/movable-window.vue';
|
|
48
|
+
import { openedOverlayBoxes } from '@/internal/opened-overlay-boxes';
|
|
49
|
+
import { nextWindowOrder } from '@/internal/window-order';
|
|
50
|
+
import type { MovableWindowDragMode } from '@/types/movable-window';
|
|
51
|
+
|
|
52
|
+
export interface Props {
|
|
53
|
+
/** 見出し。title スロットで差し替えられる */
|
|
54
|
+
title?: string;
|
|
55
|
+
/** ドラッグで移動するときに掴む範囲。body はウィンドウ全体、header は見出しだけ。未指定なら移動できない */
|
|
56
|
+
dragMode?: MovableWindowDragMode;
|
|
57
|
+
/** 暗幕のクリックで閉じる */
|
|
58
|
+
closeOnBackdrop?: boolean;
|
|
59
|
+
/** ウィンドウに暗幕とスピナーを重ね、中身を操作できなくする */
|
|
60
|
+
loading?: boolean;
|
|
61
|
+
/** 閉じるボタンの読み上げ名 */
|
|
62
|
+
closeLabel?: string;
|
|
63
|
+
}
|
|
64
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
65
|
+
title: undefined,
|
|
66
|
+
dragMode: undefined,
|
|
67
|
+
closeOnBackdrop: false,
|
|
68
|
+
loading: false,
|
|
69
|
+
closeLabel: 'Close'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export interface Emits {
|
|
73
|
+
/** 閉じるアニメーションが終わり、ボックスが取り除かれた */
|
|
74
|
+
(e: 'emit:close'): void;
|
|
75
|
+
}
|
|
76
|
+
const emit = defineEmits<Emits>();
|
|
77
|
+
|
|
78
|
+
export interface Slots {
|
|
79
|
+
/** 見出し */
|
|
80
|
+
title?(): unknown;
|
|
81
|
+
/** ウィンドウに表示する中身 */
|
|
82
|
+
default?(): unknown;
|
|
83
|
+
}
|
|
84
|
+
defineSlots<Slots>();
|
|
85
|
+
|
|
86
|
+
/** 表示するか。閉じる操作で false になる */
|
|
87
|
+
const open = defineModel<boolean>('open', { default: false });
|
|
88
|
+
|
|
89
|
+
const refWindow = ref<InstanceType<typeof MovableWindow>>();
|
|
90
|
+
const order = ref(0);
|
|
91
|
+
|
|
92
|
+
const boxKey = Symbol('dwui-overlay-box');
|
|
93
|
+
let previousFocus: HTMLElement | null = null;
|
|
94
|
+
|
|
95
|
+
const onClickBackdrop = (): void => {
|
|
96
|
+
if (props.closeOnBackdrop) {
|
|
97
|
+
open.value = false;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const onCloseWindow = (): void => {
|
|
102
|
+
open.value = false;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* ウィンドウにフォーカスがある間、Esc で閉じる。
|
|
107
|
+
* 中に置いた要素が dispatchEvent で発行した Escape、IME の変換を取り消す Esc、
|
|
108
|
+
* 中に置いた <dialog> に向けた Esc では閉じない
|
|
109
|
+
*/
|
|
110
|
+
const onKeydownWindow = (event: KeyboardEvent): void => {
|
|
111
|
+
if (event.key !== 'Escape' || !event.isTrusted || event.isComposing) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (event.target instanceof Element && event.target.closest('dialog')) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// テンプレートで box の中に置いた box の Esc は外側にもバブルするため、最後に開いた box だけが閉じる
|
|
118
|
+
if (openedOverlayBoxes.at(-1) === boxKey) {
|
|
119
|
+
open.value = false;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const onAfterLeaveOverlayBox = (): void => {
|
|
124
|
+
emit('emit:close');
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const removeFromOpenedBoxes = (): void => {
|
|
128
|
+
const index = openedOverlayBoxes.indexOf(boxKey);
|
|
129
|
+
if (0 <= index) {
|
|
130
|
+
openedOverlayBoxes.splice(index, 1);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const activate = (): void => {
|
|
135
|
+
order.value = nextWindowOrder();
|
|
136
|
+
const movable = refWindow.value;
|
|
137
|
+
const rect = movable?.element?.getBoundingClientRect();
|
|
138
|
+
if (movable) {
|
|
139
|
+
movable.position.x = (window.innerWidth - (rect?.width || 0)) / 2;
|
|
140
|
+
// 画面より高いときに見出しが上に隠れて掴めなくならないよう、上端は画面内に収める
|
|
141
|
+
movable.position.y = Math.max(0, (window.innerHeight - (rect?.height || 0)) / 2);
|
|
142
|
+
}
|
|
143
|
+
previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
144
|
+
movable?.element?.focus();
|
|
145
|
+
openedOverlayBoxes.push(boxKey);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const deactivate = (): void => {
|
|
149
|
+
refWindow.value?.teardown();
|
|
150
|
+
removeFromOpenedBoxes();
|
|
151
|
+
if (previousFocus?.isConnected) {
|
|
152
|
+
previousFocus.focus();
|
|
153
|
+
}
|
|
154
|
+
previousFocus = null;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
onMounted(() => {
|
|
158
|
+
if (open.value) {
|
|
159
|
+
activate();
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
onBeforeUnmount(() => {
|
|
164
|
+
removeFromOpenedBoxes();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
watch(open, (newValue) => {
|
|
168
|
+
if (newValue) {
|
|
169
|
+
activate();
|
|
170
|
+
} else {
|
|
171
|
+
deactivate();
|
|
172
|
+
}
|
|
173
|
+
}, { flush: 'post' });
|
|
174
|
+
</script>
|
|
175
|
+
|
|
176
|
+
<style>
|
|
177
|
+
:where(html:has(.dwui-overlay-box), html:has(.dwui-overlay-box) > body) {
|
|
178
|
+
overflow: hidden;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
:where(.dwui-overlay-box) {
|
|
182
|
+
position: fixed;
|
|
183
|
+
inset: 0;
|
|
184
|
+
z-index: calc(var(--dwui-z-index-overlay-box, 5000) + var(--dwui-order-window, 0));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
:where(.dwui-overlay-box-backdrop) {
|
|
188
|
+
position: absolute;
|
|
189
|
+
inset: 0;
|
|
190
|
+
background: var(--dwui-background-overlay-box-backdrop, light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.5)));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
:where(.dwui-overlay-box-container) {
|
|
194
|
+
--dwui-border-color-movable-window: var(--dwui-border-color-overlay-box, light-dark(#8f8f8f, #6b6f76));
|
|
195
|
+
--dwui-radius-movable-window: var(--dwui-radius-overlay-box, 4px);
|
|
196
|
+
--dwui-background-movable-window: var(--dwui-background-overlay-box, Canvas);
|
|
197
|
+
--dwui-color-text-movable-window: var(--dwui-color-text-overlay-box, CanvasText);
|
|
198
|
+
--dwui-box-shadow-movable-window: var(--dwui-box-shadow-overlay-box, 0 2px 8px rgba(0, 0, 0, 0.33));
|
|
199
|
+
--dwui-padding-movable-window-header: var(--dwui-padding-overlay-box-header, 0.17em 0.33em);
|
|
200
|
+
--dwui-background-movable-window-header: var(--dwui-background-overlay-box-header, transparent);
|
|
201
|
+
--dwui-color-text-movable-window-header: var(--dwui-color-text-overlay-box-header, inherit);
|
|
202
|
+
--dwui-background-movable-window-close-button-hover: var(--dwui-background-overlay-box-close-button-hover, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.12)));
|
|
203
|
+
--dwui-padding-movable-window-body: var(--dwui-padding-overlay-box-body, 0.4em);
|
|
204
|
+
--dwui-color-text-movable-window-resizer: var(--dwui-color-text-overlay-box-resizer, GrayText);
|
|
205
|
+
--dwui-background-movable-window-loading: var(--dwui-background-overlay-box-loading, light-dark(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.4)));
|
|
206
|
+
--dwui-size-movable-window-spinner: var(--dwui-size-overlay-box-spinner, 48px);
|
|
207
|
+
--dwui-border-color-movable-window-spinner: var(--dwui-border-color-overlay-box-spinner, light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.2)));
|
|
208
|
+
--dwui-border-color-movable-window-spinner-accent: var(--dwui-border-color-overlay-box-spinner-accent, light-dark(rgba(47, 90, 74, 0.8), rgba(140, 200, 170, 0.8)));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
:where(.dwui-overlay-box-fade-enter-active, .dwui-overlay-box-fade-leave-active) {
|
|
212
|
+
transition: opacity 0.25s ease;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
:where(.dwui-overlay-box-fade-enter-from, .dwui-overlay-box-fade-leave-to) {
|
|
216
|
+
opacity: 0;
|
|
217
|
+
}
|
|
218
|
+
</style>
|
package/src/page-section.vue
CHANGED
|
@@ -36,7 +36,7 @@ import LabelIcon from '@/label-icon.vue';
|
|
|
36
36
|
/** 見出しのアイコンとして選べるもの */
|
|
37
37
|
type PageSectionIcon = 'diamond' | 'circle' | 'square' | 'pushpin' | 'round-pushpin';
|
|
38
38
|
|
|
39
|
-
interface Props {
|
|
39
|
+
export interface Props {
|
|
40
40
|
/** 見出しの文字。未指定なら見出しを表示しない */
|
|
41
41
|
title?: string;
|
|
42
42
|
/** 見出しのアイコン。これ以外のアイコンは#iconスロットで渡す デフォルト 'diamond' */
|
|
@@ -54,7 +54,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
54
54
|
icon: 'diamond'
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
interface Slots {
|
|
57
|
+
export interface Slots {
|
|
58
58
|
/** 見出しの文字の前に表示するアイコン。iconより優先する */
|
|
59
59
|
icon?(): unknown;
|
|
60
60
|
default?(): unknown;
|
|
@@ -85,19 +85,19 @@ const presetIcon = computed((): { component: Component; props: Record<string, un
|
|
|
85
85
|
<style>
|
|
86
86
|
:where(.dwui-page-section) {
|
|
87
87
|
display: block;
|
|
88
|
-
margin:
|
|
89
|
-
padding-top:
|
|
90
|
-
font-size: var(--dwui-font-size-page-section,
|
|
88
|
+
margin: 0.33em 0 0.67em;
|
|
89
|
+
padding-top: 0.17em;
|
|
90
|
+
font-size: var(--dwui-font-size-page-section, inherit);
|
|
91
91
|
font-weight: 500;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
:where(.dwui-page-section-title) {
|
|
95
95
|
display: flex;
|
|
96
96
|
align-items: center;
|
|
97
|
-
font-size: var(--dwui-font-size-page-section-title,
|
|
97
|
+
font-size: var(--dwui-font-size-page-section-title, 1.17em);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
:where(.dwui-page-section-content) {
|
|
101
|
-
margin:
|
|
101
|
+
margin: 0.67em 0 0.67em 1.33em;
|
|
102
102
|
}
|
|
103
103
|
</style>
|
package/src/page-title.vue
CHANGED
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
<script setup lang="ts">
|
|
26
26
|
import LabelIcon from '@/label-icon.vue';
|
|
27
27
|
|
|
28
|
-
interface Props {
|
|
28
|
+
export interface Props {
|
|
29
29
|
/** タイトルの文字 */
|
|
30
30
|
title: string;
|
|
31
31
|
}
|
|
32
32
|
const props = defineProps<Props>();
|
|
33
33
|
|
|
34
|
-
interface Slots {
|
|
34
|
+
export interface Slots {
|
|
35
35
|
/** タイトルの文字の前に表示するアイコン */
|
|
36
36
|
icon?(): unknown;
|
|
37
37
|
/** タイトルバーの右側に表示する内容 */
|
|
@@ -46,11 +46,11 @@ const slots = defineSlots<Slots>();
|
|
|
46
46
|
align-items: center;
|
|
47
47
|
justify-content: space-between;
|
|
48
48
|
width: var(--dwui-width-page-title, auto);
|
|
49
|
-
padding:
|
|
49
|
+
padding: 0.33em;
|
|
50
50
|
border-radius: 4px;
|
|
51
|
-
background: var(--dwui-background-page-title, linear-gradient(#323232 0%, rgb(32, 32, 31) 25%, rgb(32, 32, 31) 75%, #323232 100%));
|
|
51
|
+
background: var(--dwui-background-page-title, linear-gradient(light-dark(#323232, #3c3f45) 0%, light-dark(rgb(32, 32, 31), #2b2d31) 25%, light-dark(rgb(32, 32, 31), #2b2d31) 75%, light-dark(#323232, #3c3f45) 100%));
|
|
52
52
|
color: var(--dwui-color-text-page-title, rgb(220, 220, 220));
|
|
53
|
-
font-size: var(--dwui-font-size-page-title,
|
|
53
|
+
font-size: var(--dwui-font-size-page-title, 1.17em);
|
|
54
54
|
font-weight: var(--dwui-font-weight-page-title, normal);
|
|
55
55
|
}
|
|
56
56
|
</style>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
画面全体を覆うローディング。
|
|
3
|
+
loading が true の間は <dialog> をモーダルで開き、暗幕とスピナーを表示して画面の操作を受け付けなくする。
|
|
4
|
+
Esc キーでは閉じない。
|
|
5
|
+
-->
|
|
6
|
+
<template>
|
|
7
|
+
<dialog
|
|
8
|
+
ref="refDialog"
|
|
9
|
+
class="dwui-screen-loading"
|
|
10
|
+
closedby="none"
|
|
11
|
+
@cancel.prevent
|
|
12
|
+
>
|
|
13
|
+
<div class="dwui-screen-loading-spinner" />
|
|
14
|
+
</dialog>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
19
|
+
|
|
20
|
+
export interface Props {
|
|
21
|
+
/** 読み込み中か */
|
|
22
|
+
loading: boolean;
|
|
23
|
+
}
|
|
24
|
+
const props = defineProps<Props>();
|
|
25
|
+
|
|
26
|
+
const refDialog = ref<HTMLDialogElement | null>(null);
|
|
27
|
+
|
|
28
|
+
const open = () => {
|
|
29
|
+
const dialog = refDialog.value;
|
|
30
|
+
if (dialog && !dialog.open) {
|
|
31
|
+
dialog.showModal();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const close = () => {
|
|
36
|
+
const dialog = refDialog.value;
|
|
37
|
+
if (dialog?.open) {
|
|
38
|
+
dialog.close();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
onMounted(() => {
|
|
43
|
+
if (props.loading) {
|
|
44
|
+
open();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
onBeforeUnmount(() => {
|
|
49
|
+
close();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
watch(() => props.loading, (newValue) => {
|
|
53
|
+
if (newValue) {
|
|
54
|
+
open();
|
|
55
|
+
} else {
|
|
56
|
+
close();
|
|
57
|
+
}
|
|
58
|
+
}, { flush: 'post' });
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<style>
|
|
62
|
+
:where(.dwui-screen-loading) {
|
|
63
|
+
padding: 0;
|
|
64
|
+
border: none;
|
|
65
|
+
outline: none;
|
|
66
|
+
background-color: transparent;
|
|
67
|
+
background-image: none;
|
|
68
|
+
overflow: visible;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:where(.dwui-screen-loading::backdrop) {
|
|
72
|
+
background: var(--dwui-background-screen-loading, light-dark(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.5)));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:where(.dwui-screen-loading-spinner) {
|
|
76
|
+
box-sizing: border-box;
|
|
77
|
+
width: var(--dwui-size-screen-loading-spinner, 100px);
|
|
78
|
+
height: var(--dwui-size-screen-loading-spinner, 100px);
|
|
79
|
+
border: 8px solid var(--dwui-border-color-screen-loading-spinner, light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.2)));
|
|
80
|
+
border-left-color: var(--dwui-border-color-screen-loading-spinner-accent, light-dark(rgba(47, 90, 74, 0.8), rgba(140, 200, 170, 0.8)));
|
|
81
|
+
border-radius: 50%;
|
|
82
|
+
animation: dwui-screen-loading-spin 1.1s linear infinite;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@keyframes dwui-screen-loading-spin {
|
|
86
|
+
to {
|
|
87
|
+
transform: rotate(360deg);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
</style>
|
package/src/tab-content.vue
CHANGED
|
@@ -4,12 +4,13 @@ TabGroupの中に置くタブ1つ分の中身
|
|
|
4
4
|
<template>
|
|
5
5
|
<div
|
|
6
6
|
v-if="!props.disabled"
|
|
7
|
+
:id="context ? `${context.groupName}-${props.tabId}-panel` : undefined"
|
|
7
8
|
class="dwui-tab-content"
|
|
8
|
-
|
|
9
|
-
:aria-
|
|
10
|
-
:aria-description="props.description"
|
|
9
|
+
role="tabpanel"
|
|
10
|
+
:aria-labelledby="context ? `${context.groupName}-${props.tabId}` : undefined"
|
|
11
11
|
:aria-busy="loading ? 'true' : undefined"
|
|
12
|
-
:
|
|
12
|
+
:hidden="!selected"
|
|
13
|
+
:data-test-tab-content="props.tabId"
|
|
13
14
|
>
|
|
14
15
|
<slot
|
|
15
16
|
:activated="activated"
|
|
@@ -38,12 +39,12 @@ import type { ClassValue, Slot, StyleValue } from 'vue';
|
|
|
38
39
|
import { tabGroupContextKey } from '@/internal/tab-group-context';
|
|
39
40
|
import type { TabContentStatus } from '@/internal/tab-group-context';
|
|
40
41
|
|
|
41
|
-
//
|
|
42
|
-
interface Props {
|
|
43
|
-
/** タブを識別するID。TabGroupの
|
|
44
|
-
|
|
42
|
+
// tabId・label・header*・status・#iconは、TabGroupが見出しを描画するために読む
|
|
43
|
+
export interface Props {
|
|
44
|
+
/** タブを識別するID。TabGroupのselectedTabIdに渡す値 */
|
|
45
|
+
tabId: string;
|
|
45
46
|
/** タブの見出しの文字 */
|
|
46
|
-
|
|
47
|
+
label: string;
|
|
47
48
|
/** trueの場合、タブを選べなくし、中身も描画しない */
|
|
48
49
|
disabled?: boolean;
|
|
49
50
|
/** タブの見出しの状態。見出しの色が変わる */
|
|
@@ -55,7 +56,7 @@ interface Props {
|
|
|
55
56
|
}
|
|
56
57
|
const props = defineProps<Props>();
|
|
57
58
|
|
|
58
|
-
interface Slots {
|
|
59
|
+
export interface Slots {
|
|
59
60
|
/** タブの見出しの文字の前に表示するアイコン */
|
|
60
61
|
icon?(): unknown;
|
|
61
62
|
/**
|
|
@@ -80,7 +81,7 @@ const loading = ref(false);
|
|
|
80
81
|
const loadingSlot = (): Slot | undefined => context?.loadingSlot();
|
|
81
82
|
|
|
82
83
|
// 表示の切り替えは初期描画から効かせるため、マウントを待たない
|
|
83
|
-
const selected = computed((): boolean => context?.
|
|
84
|
+
const selected = computed((): boolean => context?.activeTabId.value === props.tabId);
|
|
84
85
|
|
|
85
86
|
const activated = computed((): boolean => !!context?.mounted.value && selected.value);
|
|
86
87
|
|
|
@@ -95,7 +96,7 @@ const setLoading = (value: boolean) => {
|
|
|
95
96
|
</script>
|
|
96
97
|
|
|
97
98
|
<style>
|
|
98
|
-
:where(.dwui-tab-content[
|
|
99
|
+
:where(.dwui-tab-content[hidden]) {
|
|
99
100
|
display: none;
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -103,7 +104,7 @@ const setLoading = (value: boolean) => {
|
|
|
103
104
|
display: block;
|
|
104
105
|
/* 読み込み中の覆いを中身の範囲に重ねる基準にする */
|
|
105
106
|
position: relative;
|
|
106
|
-
padding:
|
|
107
|
+
padding: 0.33em 0.67em;
|
|
107
108
|
overflow: hidden;
|
|
108
109
|
/* 全幅を横断すると速度が出てカクつくため、既定は固定の移動量とease-outとフェードでスライドインする */
|
|
109
110
|
animation: dwui-tab-slide-in var(--dwui-duration-tab-slide, 0.35s) var(--dwui-easing-tab-slide, cubic-bezier(0.22, 1, 0.36, 1));
|
|
@@ -116,14 +117,14 @@ const setLoading = (value: boolean) => {
|
|
|
116
117
|
display: flex;
|
|
117
118
|
align-items: center;
|
|
118
119
|
justify-content: center;
|
|
119
|
-
background: var(--dwui-overlay-color-loading, rgba(0, 0, 0, 0.25));
|
|
120
|
+
background: var(--dwui-overlay-color-loading, light-dark(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.45)));
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
:where(.dwui-tab-loading-spinner) {
|
|
123
124
|
width: var(--dwui-size-loading-spinner, 40px);
|
|
124
125
|
height: var(--dwui-size-loading-spinner, 40px);
|
|
125
|
-
border: 4px solid var(--dwui-border-color-loading-spinner
|
|
126
|
-
border-top-color: var(--dwui-border-color-loading-spinner, #ffffff);
|
|
126
|
+
border: 4px solid var(--dwui-border-color-loading-spinner, rgba(255, 255, 255, 0.4));
|
|
127
|
+
border-top-color: var(--dwui-border-color-loading-spinner-accent, #ffffff);
|
|
127
128
|
border-radius: 50%;
|
|
128
129
|
animation: dwui-tab-loading-spin 0.8s linear infinite;
|
|
129
130
|
}
|