@digitalwalletcorp/vue-core 1.0.1 → 1.2.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 +7 -4
- package/lib/accordion-fieldset.cjs +1 -1
- package/lib/accordion-fieldset.d.cts +25 -0
- package/lib/accordion-fieldset.d.ts +0 -2
- package/lib/accordion-fieldset.js +1 -1
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-n-IZxUiu.js +66 -0
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-t9NqmoZW.cjs +1 -0
- package/lib/accordion-section.cjs +1 -0
- package/lib/accordion-section.d.cts +34 -0
- package/lib/accordion-section.d.ts +34 -0
- package/lib/accordion-section.js +4 -0
- package/lib/accordion-section.vue_vue_type_style_index_0_lang-CFDdUEnn.cjs +1 -0
- package/lib/accordion-section.vue_vue_type_style_index_0_lang-Gvjjx02P.js +78 -0
- package/lib/components-CNOeuZPu.cjs +1 -0
- package/lib/components-DBK8NUBh.js +24 -0
- package/lib/components.d.cts +9 -0
- package/lib/components.d.ts +3 -0
- package/lib/global.d.cts +7 -0
- package/lib/hourglass-loading.d.cts +23 -0
- package/lib/index.cjs +1 -1
- package/lib/index.d.cts +3 -0
- package/lib/index.js +18 -12
- package/lib/internal/tab-group-context.d.cts +16 -0
- package/lib/internal/use-shrinkable.d.cts +12 -0
- package/lib/internal/use-shrinkable.d.ts +12 -0
- package/lib/label-button.cjs +1 -1
- package/lib/label-button.d.cts +30 -0
- package/lib/label-button.js +1 -1
- package/lib/{label-button.vue_vue_type_script_setup_true_lang-DqhdCgmJ.cjs → label-button.vue_vue_type_script_setup_true_lang-BwVOxaJP.cjs} +1 -1
- package/lib/{label-button.vue_vue_type_script_setup_true_lang-CoHrTUSs.js → label-button.vue_vue_type_script_setup_true_lang-DorC4pKz.js} +1 -1
- package/lib/label-icon.cjs +1 -1
- package/lib/label-icon.d.cts +30 -0
- package/lib/label-icon.js +1 -1
- package/lib/{label-icon.vue_vue_type_style_index_0_lang-C2URq6GP.cjs → label-icon.vue_vue_type_style_index_0_lang-D9Cimu20.cjs} +1 -1
- package/lib/{label-icon.vue_vue_type_style_index_0_lang-bQFkQ_gC.js → label-icon.vue_vue_type_style_index_0_lang-me52HE2V.js} +1 -1
- package/lib/nuxt.cjs +1 -1
- package/lib/nuxt.d.cts +10 -0
- package/lib/nuxt.js +1 -1
- package/lib/page-section.cjs +1 -0
- package/lib/page-section.d.cts +34 -0
- package/lib/page-section.d.ts +34 -0
- package/lib/page-section.js +4 -0
- package/lib/page-section.vue_vue_type_style_index_0_lang-DEAkTLxd.cjs +1 -0
- package/lib/page-section.vue_vue_type_style_index_0_lang-DpVQe_rV.js +54 -0
- package/lib/page-title.cjs +1 -0
- package/lib/page-title.d.cts +20 -0
- package/lib/page-title.d.ts +20 -0
- package/lib/page-title.js +4 -0
- package/lib/page-title.vue_vue_type_style_index_0_lang-BqIsIks5.cjs +1 -0
- package/lib/page-title.vue_vue_type_style_index_0_lang-ChZot85K.js +36 -0
- package/lib/register.cjs +1 -1
- package/lib/register.d.cts +9 -0
- package/lib/register.js +1 -1
- package/lib/style.css +1 -1
- package/lib/tab-content.d.cts +39 -0
- package/lib/tab-group.cjs +1 -1
- package/lib/tab-group.d.cts +44 -0
- package/lib/tab-group.js +1 -1
- package/lib/{tab-group.vue_vue_type_style_index_0_lang-CjnBkvvZ.js → tab-group.vue_vue_type_style_index_0_lang-C84mDEOC.js} +1 -1
- package/lib/{tab-group.vue_vue_type_style_index_0_lang-CwVGYZAo.cjs → tab-group.vue_vue_type_style_index_0_lang-CMaufRJV.cjs} +1 -1
- package/lib/types/label-preset.d.cts +12 -0
- package/lib/use-shrinkable-CS2bmsJJ.js +17 -0
- package/lib/use-shrinkable-Cu9JQZll.cjs +1 -0
- package/package.json +25 -10
- package/src/accordion-fieldset.vue +4 -35
- package/src/accordion-section.vue +194 -0
- package/src/components.ts +3 -0
- package/src/internal/use-shrinkable.ts +37 -0
- package/src/label-icon.vue +2 -2
- package/src/page-section.vue +103 -0
- package/src/page-title.vue +56 -0
- package/src/tab-content.vue +7 -7
- package/src/tab-group.vue +15 -15
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-Cod0KnrE.cjs +0 -1
- package/lib/accordion-fieldset.vue_vue_type_style_index_0_lang-Dk5Id0dl.js +0 -79
- package/lib/components-CvmuAs2C.cjs +0 -1
- package/lib/components-p1BluzXb.js +0 -18
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
中身を開閉できる領域。中身の下に開閉ボタンを置く
|
|
3
|
+
-->
|
|
4
|
+
<template>
|
|
5
|
+
<div class="dwui-accordion-section">
|
|
6
|
+
<div
|
|
7
|
+
ref="refContents"
|
|
8
|
+
class="dwui-accordion-section-contents"
|
|
9
|
+
:class="[
|
|
10
|
+
shrinkable ? pageContext.expanded ? 'dwui-expanded' : 'dwui-shrunk' : '',
|
|
11
|
+
{ 'dwui-no-gradient': props.noGradient }
|
|
12
|
+
]"
|
|
13
|
+
>
|
|
14
|
+
<slot />
|
|
15
|
+
</div>
|
|
16
|
+
<div
|
|
17
|
+
v-if="shrinkable"
|
|
18
|
+
class="dwui-accordion-section-control"
|
|
19
|
+
>
|
|
20
|
+
<button
|
|
21
|
+
type="button"
|
|
22
|
+
class="dwui-accordion-section-toggle"
|
|
23
|
+
:disabled="props.disabled"
|
|
24
|
+
:aria-expanded="pageContext.expanded"
|
|
25
|
+
@click.stop="onClickToggle"
|
|
26
|
+
>
|
|
27
|
+
<LabelIcon v-if="toggleIcon() != null || toggleLabel != null">
|
|
28
|
+
<template
|
|
29
|
+
v-if="toggleIcon() != null"
|
|
30
|
+
#icon
|
|
31
|
+
>
|
|
32
|
+
<component
|
|
33
|
+
:is="toggleIcon()"
|
|
34
|
+
v-bind="toggleIconProps()"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
37
|
+
<template
|
|
38
|
+
v-if="toggleLabel != null"
|
|
39
|
+
#default
|
|
40
|
+
>
|
|
41
|
+
{{ toggleLabel }}
|
|
42
|
+
</template>
|
|
43
|
+
</LabelIcon>
|
|
44
|
+
<SvgTriangleButton
|
|
45
|
+
v-else
|
|
46
|
+
:direction="pageContext.expanded ? 'up' : 'down'"
|
|
47
|
+
/>
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { computed, onMounted, reactive, ref } from 'vue';
|
|
55
|
+
import type { Component, Slot } from 'vue';
|
|
56
|
+
import { SvgTriangleButton } from '@digitalwalletcorp/vue-svg-icons';
|
|
57
|
+
import LabelIcon from '@/label-icon.vue';
|
|
58
|
+
import { useShrinkable } from '@/internal/use-shrinkable';
|
|
59
|
+
import type { LabelPreset } from '@/types/label-preset';
|
|
60
|
+
|
|
61
|
+
// 開閉ボタンのアイコンとラベルは別々に決める。どちらも、スロット/ラベルの指定 > プリセット の順で使う
|
|
62
|
+
// 何も指定が無い場合だけ、既定の三角を表示する
|
|
63
|
+
interface Props {
|
|
64
|
+
/** trueの場合、開閉ボタンを無効にする */
|
|
65
|
+
disabled?: boolean;
|
|
66
|
+
/** trueの場合、開いた状態で表示する デフォルト false */
|
|
67
|
+
initialExpand?: boolean;
|
|
68
|
+
/** trueの場合、縮めたときに中身の下側をぼかさない */
|
|
69
|
+
noGradient?: boolean;
|
|
70
|
+
/** 縮めているときの開閉ボタン(開く)のラベル */
|
|
71
|
+
openLabel?: string;
|
|
72
|
+
/** 開いているときの開閉ボタン(閉じる)のラベル */
|
|
73
|
+
closeLabel?: string;
|
|
74
|
+
/** 縮めているときの開閉ボタン(開く)のアイコンとラベル */
|
|
75
|
+
openPreset?: LabelPreset;
|
|
76
|
+
/** 開いているときの開閉ボタン(閉じる)のアイコンとラベル */
|
|
77
|
+
closePreset?: LabelPreset;
|
|
78
|
+
}
|
|
79
|
+
const props = defineProps<Props>();
|
|
80
|
+
|
|
81
|
+
interface Slots {
|
|
82
|
+
/** 縮めているときの開閉ボタン(開く)のアイコン */
|
|
83
|
+
'open-icon'?(): unknown;
|
|
84
|
+
/** 開いているときの開閉ボタン(閉じる)のアイコン */
|
|
85
|
+
'close-icon'?(): unknown;
|
|
86
|
+
default?(): unknown;
|
|
87
|
+
}
|
|
88
|
+
const slots = defineSlots<Slots>();
|
|
89
|
+
|
|
90
|
+
const refContents = ref<HTMLElement>();
|
|
91
|
+
const pageContext = reactive({
|
|
92
|
+
expanded: true
|
|
93
|
+
});
|
|
94
|
+
const shrinkable = useShrinkable(refContents);
|
|
95
|
+
|
|
96
|
+
const togglePreset = computed((): LabelPreset | undefined => pageContext.expanded ? props.closePreset : props.openPreset);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 開閉ボタンに表示するアイコン。スロットは関数のままコンポーネントとして描画する
|
|
100
|
+
* スロットはリアクティブではないため、computedでキャッシュせず描画のたびに取り出す
|
|
101
|
+
*
|
|
102
|
+
* @returns {Slot | Component | undefined}
|
|
103
|
+
*/
|
|
104
|
+
const toggleIcon = (): Slot | Component | undefined => {
|
|
105
|
+
const slot = pageContext.expanded ? slots['close-icon'] : slots['open-icon'];
|
|
106
|
+
return (slot as Slot | undefined) ?? togglePreset.value?.icon;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* プリセットのアイコンに渡すProps。スロットで渡したアイコンには渡さない
|
|
111
|
+
*
|
|
112
|
+
* @returns {Record<string, unknown> | undefined}
|
|
113
|
+
*/
|
|
114
|
+
const toggleIconProps = (): Record<string, unknown> | undefined => {
|
|
115
|
+
const slot = pageContext.expanded ? slots['close-icon'] : slots['open-icon'];
|
|
116
|
+
return slot == null ? togglePreset.value?.iconProps : undefined;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const toggleLabel = computed((): string | undefined => {
|
|
120
|
+
const label = pageContext.expanded ? props.closeLabel : props.openLabel;
|
|
121
|
+
if (label != null) {
|
|
122
|
+
return label;
|
|
123
|
+
}
|
|
124
|
+
const presetLabel = togglePreset.value?.label;
|
|
125
|
+
return typeof presetLabel === 'function' ? presetLabel() : presetLabel;
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const onClickToggle = () => {
|
|
129
|
+
pageContext.expanded = !pageContext.expanded;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
pageContext.expanded = !!props.initialExpand;
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<style>
|
|
138
|
+
:where(.dwui-accordion-section) {
|
|
139
|
+
position: relative;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
:where(.dwui-accordion-section-contents) {
|
|
143
|
+
position: relative;
|
|
144
|
+
width: fit-content;
|
|
145
|
+
overflow: hidden;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
:where(.dwui-accordion-section-contents.dwui-expanded) {
|
|
149
|
+
transition: all 0.3s linear;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
:where(.dwui-accordion-section-contents.dwui-shrunk) {
|
|
153
|
+
height: auto;
|
|
154
|
+
max-height: 70px;
|
|
155
|
+
transition: all 0.3s linear;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* 縮めたときは中身の下側を背景色へ溶け込ませ、続きがあることを示す */
|
|
159
|
+
:where(.dwui-accordion-section-contents.dwui-shrunk:not(.dwui-no-gradient))::after {
|
|
160
|
+
content: '';
|
|
161
|
+
position: absolute;
|
|
162
|
+
inset: 0;
|
|
163
|
+
background-image: linear-gradient(180deg, transparent 0%, transparent 60%, var(--dwui-color-accordion-section-fade, Canvas) 100%);
|
|
164
|
+
pointer-events: none;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
:where(.dwui-accordion-section-control) {
|
|
168
|
+
/* 中身(position: relative)より後に描き、縮めたときに重ねたボタンがぼかしの下に隠れないようにする */
|
|
169
|
+
position: relative;
|
|
170
|
+
display: flex;
|
|
171
|
+
justify-content: center;
|
|
172
|
+
width: 100%;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:where(.dwui-accordion-section-toggle) {
|
|
176
|
+
display: inline-flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
:where(.dwui-accordion-section-toggle:disabled) {
|
|
182
|
+
opacity: 0.6;
|
|
183
|
+
cursor: not-allowed;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
:where(.dwui-accordion-section-toggle[aria-expanded='true']) {
|
|
187
|
+
margin-top: 8px;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* 縮めたときはボタンを中身のぼかしに少し重ね、中身とボタンの間を詰める */
|
|
191
|
+
:where(.dwui-accordion-section-toggle[aria-expanded='false']) {
|
|
192
|
+
margin-top: -10px;
|
|
193
|
+
}
|
|
194
|
+
</style>
|
package/src/components.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// 公開するコンポーネントをここに列挙する。index/register/nuxtはここから読む
|
|
2
2
|
export { default as AccordionFieldset } from '@/accordion-fieldset.vue';
|
|
3
|
+
export { default as AccordionSection } from '@/accordion-section.vue';
|
|
3
4
|
export { default as HourglassLoading } from '@/hourglass-loading.vue';
|
|
4
5
|
export { default as LabelButton } from '@/label-button.vue';
|
|
5
6
|
export { default as LabelIcon } from '@/label-icon.vue';
|
|
7
|
+
export { default as PageSection } from '@/page-section.vue';
|
|
8
|
+
export { default as PageTitle } from '@/page-title.vue';
|
|
6
9
|
export { default as TabContent } from '@/tab-content.vue';
|
|
7
10
|
export { default as TabGroup } from '@/tab-group.vue';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
|
2
|
+
import type { Ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
/** 縮めたときの中身の高さ(px)。中身がこれより低い場合は開閉しない */
|
|
5
|
+
export const SHRUNK_HEIGHT = 70;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 中身が縮めたときの高さ以上あり、開閉できるかを返す
|
|
9
|
+
* 中身の大きさが変わるたびに測り直すため、隠れたタブの中にあって後から表示された場合や、中身が増減した場合も再判定される
|
|
10
|
+
* 縮めている間も中身の本来の高さで判定する
|
|
11
|
+
*
|
|
12
|
+
* @param {Ref<HTMLElement | undefined>} contents 開閉する中身の要素
|
|
13
|
+
* @returns {Ref<boolean>}
|
|
14
|
+
*/
|
|
15
|
+
export function useShrinkable(contents: Ref<HTMLElement | undefined>): Ref<boolean> {
|
|
16
|
+
// 測るまではSSRの出力と揃えるため、開閉できるものとして扱う
|
|
17
|
+
const shrinkable = ref(true);
|
|
18
|
+
let resizeObserver: ResizeObserver | undefined;
|
|
19
|
+
|
|
20
|
+
onMounted(() => {
|
|
21
|
+
const element = contents.value;
|
|
22
|
+
if (element == null) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// 監視を始めた時点でも1回呼ばれる
|
|
26
|
+
resizeObserver = new ResizeObserver(() => {
|
|
27
|
+
shrinkable.value = SHRUNK_HEIGHT <= element.scrollHeight;
|
|
28
|
+
});
|
|
29
|
+
resizeObserver.observe(element);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
onBeforeUnmount(() => {
|
|
33
|
+
resizeObserver?.disconnect();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return shrinkable;
|
|
37
|
+
}
|
package/src/label-icon.vue
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<template>
|
|
5
5
|
<span
|
|
6
6
|
class="dwui-label-icon"
|
|
7
|
-
:style="props.gap == null ? undefined : { '--dwui-label-icon
|
|
7
|
+
:style="props.gap == null ? undefined : { '--dwui-gap-label-icon': props.gap }"
|
|
8
8
|
>
|
|
9
9
|
<slot name="icon">
|
|
10
10
|
<component
|
|
@@ -70,6 +70,6 @@ const slots = defineSlots<Slots>();
|
|
|
70
70
|
|
|
71
71
|
/* アイコンとラベルの間隔。gapはflex専用のためmarginで空ける */
|
|
72
72
|
:where(.dwui-label-icon > .dwui-label:not(:first-child)) {
|
|
73
|
-
margin-left: var(--dwui-label-icon
|
|
73
|
+
margin-left: var(--dwui-gap-label-icon, 0.25em);
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
見出し付きの区画
|
|
3
|
+
-->
|
|
4
|
+
<template>
|
|
5
|
+
<section class="dwui-page-section">
|
|
6
|
+
<div
|
|
7
|
+
v-if="props.title != null"
|
|
8
|
+
class="dwui-page-section-title"
|
|
9
|
+
:class="props.titleClass"
|
|
10
|
+
:style="props.titleStyle"
|
|
11
|
+
>
|
|
12
|
+
<LabelIcon>
|
|
13
|
+
<template #icon>
|
|
14
|
+
<slot name="icon">
|
|
15
|
+
<component
|
|
16
|
+
:is="presetIcon.component"
|
|
17
|
+
v-bind="presetIcon.props"
|
|
18
|
+
/>
|
|
19
|
+
</slot>
|
|
20
|
+
</template>
|
|
21
|
+
{{ props.title }}
|
|
22
|
+
</LabelIcon>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="dwui-page-section-content">
|
|
25
|
+
<slot />
|
|
26
|
+
</div>
|
|
27
|
+
</section>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup lang="ts">
|
|
31
|
+
import { computed } from 'vue';
|
|
32
|
+
import type { ClassValue, Component, StyleValue } from 'vue';
|
|
33
|
+
import { SvgCircle, SvgDiamond, SvgPushpin, SvgRoundPushpin, SvgSquare } from '@digitalwalletcorp/vue-svg-icons';
|
|
34
|
+
import LabelIcon from '@/label-icon.vue';
|
|
35
|
+
|
|
36
|
+
/** 見出しのアイコンとして選べるもの */
|
|
37
|
+
type PageSectionIcon = 'diamond' | 'circle' | 'square' | 'pushpin' | 'round-pushpin';
|
|
38
|
+
|
|
39
|
+
interface Props {
|
|
40
|
+
/** 見出しの文字。未指定なら見出しを表示しない */
|
|
41
|
+
title?: string;
|
|
42
|
+
/** 見出しのアイコン。これ以外のアイコンは#iconスロットで渡す デフォルト 'diamond' */
|
|
43
|
+
icon?: PageSectionIcon;
|
|
44
|
+
/** diamond・circle・squareの大きさ。未指定ならアイコンの既定値(large) */
|
|
45
|
+
iconVariant?: 'large' | 'medium' | 'small';
|
|
46
|
+
/** diamond・circle・squareの色。未指定ならdiamondは#1a44b6、circleは#e78b2f、squareは#d13a2b */
|
|
47
|
+
iconColor?: string;
|
|
48
|
+
/** 見出しに付けるclass */
|
|
49
|
+
titleClass?: ClassValue;
|
|
50
|
+
/** 見出しに付けるstyle */
|
|
51
|
+
titleStyle?: StyleValue;
|
|
52
|
+
}
|
|
53
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
54
|
+
icon: 'diamond'
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
interface Slots {
|
|
58
|
+
/** 見出しの文字の前に表示するアイコン。iconより優先する */
|
|
59
|
+
icon?(): unknown;
|
|
60
|
+
default?(): unknown;
|
|
61
|
+
}
|
|
62
|
+
defineSlots<Slots>();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* プリセットのアイコン。shapeがtrueのものは、大きさと色を受け取る
|
|
66
|
+
* 見出しの既定のアイコンの色は、アイコン側の既定値が変わっても変わらないようにここで持つ
|
|
67
|
+
*/
|
|
68
|
+
const PRESET_ICONS: Record<PageSectionIcon, { component: Component; shape: boolean; color?: string }> = {
|
|
69
|
+
'diamond': { component: SvgDiamond, shape: true, color: '#1a44b6' },
|
|
70
|
+
'circle': { component: SvgCircle, shape: true, color: '#e78b2f' },
|
|
71
|
+
'square': { component: SvgSquare, shape: true, color: '#d13a2b' },
|
|
72
|
+
'pushpin': { component: SvgPushpin, shape: false },
|
|
73
|
+
'round-pushpin': { component: SvgRoundPushpin, shape: false }
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const presetIcon = computed((): { component: Component; props: Record<string, unknown> } => {
|
|
77
|
+
const preset = PRESET_ICONS[props.icon];
|
|
78
|
+
return {
|
|
79
|
+
component: preset.component,
|
|
80
|
+
props: preset.shape ? { variant: props.iconVariant, color: props.iconColor ?? preset.color } : {}
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<style>
|
|
86
|
+
:where(.dwui-page-section) {
|
|
87
|
+
display: block;
|
|
88
|
+
margin: 4px 0 8px;
|
|
89
|
+
padding-top: 2px;
|
|
90
|
+
font-size: var(--dwui-font-size-page-section, 12px);
|
|
91
|
+
font-weight: 500;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:where(.dwui-page-section-title) {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
font-size: var(--dwui-font-size-page-section-title, 14px);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
:where(.dwui-page-section-content) {
|
|
101
|
+
margin: 8px 0 8px 16px;
|
|
102
|
+
}
|
|
103
|
+
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
画面のタイトルバー。右側にスロットで渡されたものを space-between で配置する。
|
|
3
|
+
-->
|
|
4
|
+
<template>
|
|
5
|
+
<section class="dwui-page-title">
|
|
6
|
+
<LabelIcon class="dwui-page-title-label">
|
|
7
|
+
<!-- 渡されたスロットだけを中継する。空のスロットを渡すとアイコンの位置に間隔が空くため -->
|
|
8
|
+
<template
|
|
9
|
+
v-if="slots.icon != null"
|
|
10
|
+
#icon
|
|
11
|
+
>
|
|
12
|
+
<slot name="icon" />
|
|
13
|
+
</template>
|
|
14
|
+
{{ props.title }}
|
|
15
|
+
</LabelIcon>
|
|
16
|
+
<span
|
|
17
|
+
v-if="slots.default != null"
|
|
18
|
+
class="dwui-page-title-actions"
|
|
19
|
+
>
|
|
20
|
+
<slot />
|
|
21
|
+
</span>
|
|
22
|
+
</section>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import LabelIcon from '@/label-icon.vue';
|
|
27
|
+
|
|
28
|
+
interface Props {
|
|
29
|
+
/** タイトルの文字 */
|
|
30
|
+
title: string;
|
|
31
|
+
}
|
|
32
|
+
const props = defineProps<Props>();
|
|
33
|
+
|
|
34
|
+
interface Slots {
|
|
35
|
+
/** タイトルの文字の前に表示するアイコン */
|
|
36
|
+
icon?(): unknown;
|
|
37
|
+
/** タイトルバーの右側に表示する内容 */
|
|
38
|
+
default?(): unknown;
|
|
39
|
+
}
|
|
40
|
+
const slots = defineSlots<Slots>();
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
:where(.dwui-page-title) {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: space-between;
|
|
48
|
+
width: var(--dwui-width-page-title, auto);
|
|
49
|
+
padding: 4px;
|
|
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%));
|
|
52
|
+
color: var(--dwui-color-text-page-title, rgb(220, 220, 220));
|
|
53
|
+
font-size: var(--dwui-font-size-page-title, 14px);
|
|
54
|
+
font-weight: var(--dwui-font-weight-page-title, normal);
|
|
55
|
+
}
|
|
56
|
+
</style>
|
package/src/tab-content.vue
CHANGED
|
@@ -106,7 +106,7 @@ const setLoading = (value: boolean) => {
|
|
|
106
106
|
padding: 4px 8px;
|
|
107
107
|
overflow: hidden;
|
|
108
108
|
/* 全幅を横断すると速度が出てカクつくため、既定は固定の移動量とease-outとフェードでスライドインする */
|
|
109
|
-
animation: dwui-tab-slide-in var(--dwui-tab-slide
|
|
109
|
+
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));
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
:where(.dwui-tab-loading) {
|
|
@@ -116,14 +116,14 @@ const setLoading = (value: boolean) => {
|
|
|
116
116
|
display: flex;
|
|
117
117
|
align-items: center;
|
|
118
118
|
justify-content: center;
|
|
119
|
-
background: var(--dwui-loading
|
|
119
|
+
background: var(--dwui-overlay-color-loading, rgba(0, 0, 0, 0.25));
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
:where(.dwui-tab-loading-spinner) {
|
|
123
|
-
width: var(--dwui-loading-spinner
|
|
124
|
-
height: var(--dwui-loading-spinner
|
|
125
|
-
border: 4px solid var(--dwui-loading-spinner-track, rgba(255, 255, 255, 0.4));
|
|
126
|
-
border-top-color: var(--dwui-loading-spinner
|
|
123
|
+
width: var(--dwui-size-loading-spinner, 40px);
|
|
124
|
+
height: var(--dwui-size-loading-spinner, 40px);
|
|
125
|
+
border: 4px solid var(--dwui-border-color-loading-spinner-track, rgba(255, 255, 255, 0.4));
|
|
126
|
+
border-top-color: var(--dwui-border-color-loading-spinner, #ffffff);
|
|
127
127
|
border-radius: 50%;
|
|
128
128
|
animation: dwui-tab-loading-spin 0.8s linear infinite;
|
|
129
129
|
}
|
|
@@ -137,7 +137,7 @@ const setLoading = (value: boolean) => {
|
|
|
137
137
|
@keyframes dwui-tab-slide-in {
|
|
138
138
|
0% {
|
|
139
139
|
opacity: 0;
|
|
140
|
-
transform: translateX(var(--dwui-tab-slide
|
|
140
|
+
transform: translateX(var(--dwui-distance-tab-slide, -128px));
|
|
141
141
|
}
|
|
142
142
|
100% {
|
|
143
143
|
opacity: 1;
|
package/src/tab-group.vue
CHANGED
|
@@ -190,56 +190,56 @@ const onChangeTab = (labelId: string) => {
|
|
|
190
190
|
display: block;
|
|
191
191
|
min-width: 100px;
|
|
192
192
|
padding: 0 4px;
|
|
193
|
-
border: 1px solid var(--dwui-tab
|
|
194
|
-
border-bottom: 1px solid var(--dwui-tab-header-accent, #5ab4bd);
|
|
195
|
-
background: var(--dwui-tab-header
|
|
193
|
+
border: 1px solid var(--dwui-border-color-tab, #565656);
|
|
194
|
+
border-bottom: 1px solid var(--dwui-border-color-tab-header-accent, #5ab4bd);
|
|
195
|
+
background: var(--dwui-background-tab-header, linear-gradient(#1313c7, navy));
|
|
196
196
|
line-height: 2em;
|
|
197
197
|
text-align: center;
|
|
198
198
|
white-space: nowrap;
|
|
199
|
-
color: var(--dwui-tab-header
|
|
199
|
+
color: var(--dwui-color-text-tab-header, azure);
|
|
200
200
|
text-overflow: ellipsis;
|
|
201
201
|
cursor: pointer;
|
|
202
202
|
transition: all 0.2s ease;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
:where(.dwui-tab-radio:checked + .dwui-tab-item) {
|
|
206
|
-
background: var(--dwui-tab-header-selected
|
|
207
|
-
color: var(--dwui-tab-header-selected
|
|
206
|
+
background: var(--dwui-background-tab-header-selected, linear-gradient(#1313c7, rgb(149, 149, 234), #1313c7));
|
|
207
|
+
color: var(--dwui-color-text-tab-header-selected, azure);
|
|
208
208
|
/* 選択済みのタブは操作の対象ではないためカーソルを既定にする */
|
|
209
209
|
cursor: default;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
:where(.dwui-tab-radio:disabled + .dwui-tab-item) {
|
|
213
|
-
background: var(--dwui-tab-header-disabled
|
|
213
|
+
background: var(--dwui-background-tab-header-disabled, gray);
|
|
214
214
|
cursor: not-allowed;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
:where(.dwui-tab-item.dwui-tab-warn) {
|
|
218
|
-
background: var(--dwui-tab-header-warn
|
|
219
|
-
color: var(--dwui-tab-header-warn
|
|
218
|
+
background: var(--dwui-background-tab-header-warn, #efef13);
|
|
219
|
+
color: var(--dwui-color-text-tab-header-warn, midnightblue);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
:where(.dwui-tab-radio:checked + .dwui-tab-item.dwui-tab-warn) {
|
|
223
|
-
background: var(--dwui-tab-header-warn-selected
|
|
223
|
+
background: var(--dwui-background-tab-header-warn-selected, linear-gradient(#fafa06, rgb(232, 238, 206), #fafa06));
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
:where(.dwui-tab-item.dwui-tab-error) {
|
|
227
|
-
background: var(--dwui-tab-header-error
|
|
228
|
-
color: var(--dwui-tab-header-error
|
|
227
|
+
background: var(--dwui-background-tab-header-error, red);
|
|
228
|
+
color: var(--dwui-color-text-tab-header-error, azure);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
:where(.dwui-tab-radio:checked + .dwui-tab-item.dwui-tab-error) {
|
|
232
|
-
background: var(--dwui-tab-header-error-selected
|
|
232
|
+
background: var(--dwui-background-tab-header-error-selected, linear-gradient(#ff0000, rgb(240, 136, 136), #ff0000));
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
:where(.dwui-tab-radio:not(:checked) + .dwui-tab-item:hover) {
|
|
236
236
|
/* 背景の上に半透明の白を重ね、枠線と文字はそのままで背景だけを明るくする */
|
|
237
|
-
box-shadow: inset 0 0 0 999px var(--dwui-tab-header-hover
|
|
237
|
+
box-shadow: inset 0 0 0 999px var(--dwui-overlay-color-tab-header-hover, rgba(255, 255, 255, 0.35));
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
:where(.dwui-tab-items) {
|
|
241
241
|
height: 100%;
|
|
242
|
-
border: 1px solid var(--dwui-tab
|
|
242
|
+
border: 1px solid var(--dwui-border-color-tab, #565656);
|
|
243
243
|
/* 中身を切り替えたときのスライドを枠内に収める */
|
|
244
244
|
overflow: hidden;
|
|
245
245
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const e=require("vue"),i=require("@digitalwalletcorp/vue-svg-icons"),c=require("./label-icon.vue_vue_type_style_index_0_lang-C2URq6GP.cjs"),u=["disabled"],p=["aria-expanded"],f=70,g=e.defineComponent({__name:"accordion-fieldset",props:{legend:{},disabled:{type:Boolean},initialExpand:{type:Boolean},observer:{}},setup(s){const t=s,d=e.useSlots(),l=e.ref(),n=e.reactive({expandable:!0,expanded:!0}),r=()=>{n.expanded=!n.expanded,n.expandable=a()},a=()=>{if(l.value){const o=l.value.getBoundingClientRect();return f<=o.height}return!1};return e.onMounted(()=>{n.expanded=!!t.initialExpand,t.observer&&(n.expandable=a())}),e.watch(()=>t.observer,o=>{o&&(n.expandable=a())},{deep:!0,flush:"post"}),(o,x)=>(e.openBlock(),e.createElementBlock("fieldset",{class:"dwui-accordion-fieldset",disabled:t.disabled},[e.createElementVNode("legend",null,[e.createElementVNode("button",{type:"button",class:"dwui-accordion-toggle","aria-expanded":n.expanded,onClick:r},[e.createVNode(e.unref(i.SvgTriangleButton),{direction:n.expanded?"up":"down"},null,8,["direction"]),t.legend!=null||d.legend!=null||d.icon!=null?(e.openBlock(),e.createBlock(c._sfc_main,{key:0},e.createSlots({_:2},[d.icon!=null?{name:"icon",fn:e.withCtx(()=>[e.renderSlot(o.$slots,"icon")]),key:"0"}:void 0,t.legend!=null||d.legend!=null?{name:"default",fn:e.withCtx(()=>[e.renderSlot(o.$slots,"legend",{},()=>[e.createTextVNode(e.toDisplayString(t.legend),1)])]),key:"1"}:void 0]),1024)):e.createCommentVNode("",!0)],8,p)]),e.createElementVNode("div",{ref_key:"refContents",ref:l,class:e.normalizeClass(["dwui-accordion-contents",n.expandable?n.expanded?"dwui-expanded":"dwui-shrunk":""])},[e.renderSlot(o.$slots,"default")],2)],8,u))}});exports._sfc_main=g;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { defineComponent as u, useSlots as f, ref as x, reactive as g, onMounted as m, watch as b, openBlock as s, createElementBlock as _, createElementVNode as a, createVNode as k, unref as h, createBlock as v, createSlots as C, withCtx as r, renderSlot as i, createTextVNode as w, toDisplayString as y, createCommentVNode as B, normalizeClass as E } from "vue";
|
|
2
|
-
import { SvgTriangleButton as S } from "@digitalwalletcorp/vue-svg-icons";
|
|
3
|
-
import { _ as N } from "./label-icon.vue_vue_type_style_index_0_lang-bQFkQ_gC.js";
|
|
4
|
-
const T = ["disabled"], V = ["aria-expanded"], $ = 70, G = /* @__PURE__ */ u({
|
|
5
|
-
__name: "accordion-fieldset",
|
|
6
|
-
props: {
|
|
7
|
-
legend: {},
|
|
8
|
-
disabled: { type: Boolean },
|
|
9
|
-
initialExpand: { type: Boolean },
|
|
10
|
-
observer: {}
|
|
11
|
-
},
|
|
12
|
-
setup(c) {
|
|
13
|
-
const n = c, o = f(), d = x(), e = g({
|
|
14
|
-
expandable: !0,
|
|
15
|
-
expanded: !0
|
|
16
|
-
}), p = () => {
|
|
17
|
-
e.expanded = !e.expanded, e.expandable = l();
|
|
18
|
-
}, l = () => {
|
|
19
|
-
if (d.value) {
|
|
20
|
-
const t = d.value.getBoundingClientRect();
|
|
21
|
-
return $ <= t.height;
|
|
22
|
-
}
|
|
23
|
-
return !1;
|
|
24
|
-
};
|
|
25
|
-
return m(() => {
|
|
26
|
-
e.expanded = !!n.initialExpand, n.observer && (e.expandable = l());
|
|
27
|
-
}), b(() => n.observer, (t) => {
|
|
28
|
-
t && (e.expandable = l());
|
|
29
|
-
}, {
|
|
30
|
-
deep: !0,
|
|
31
|
-
// 高さの計測はDOM反映後に行う
|
|
32
|
-
flush: "post"
|
|
33
|
-
}), (t, H) => (s(), _("fieldset", {
|
|
34
|
-
class: "dwui-accordion-fieldset",
|
|
35
|
-
disabled: n.disabled
|
|
36
|
-
}, [
|
|
37
|
-
a("legend", null, [
|
|
38
|
-
a("button", {
|
|
39
|
-
type: "button",
|
|
40
|
-
class: "dwui-accordion-toggle",
|
|
41
|
-
"aria-expanded": e.expanded,
|
|
42
|
-
onClick: p
|
|
43
|
-
}, [
|
|
44
|
-
k(h(S), {
|
|
45
|
-
direction: e.expanded ? "up" : "down"
|
|
46
|
-
}, null, 8, ["direction"]),
|
|
47
|
-
n.legend != null || o.legend != null || o.icon != null ? (s(), v(N, { key: 0 }, C({ _: 2 }, [
|
|
48
|
-
o.icon != null ? {
|
|
49
|
-
name: "icon",
|
|
50
|
-
fn: r(() => [
|
|
51
|
-
i(t.$slots, "icon")
|
|
52
|
-
]),
|
|
53
|
-
key: "0"
|
|
54
|
-
} : void 0,
|
|
55
|
-
n.legend != null || o.legend != null ? {
|
|
56
|
-
name: "default",
|
|
57
|
-
fn: r(() => [
|
|
58
|
-
i(t.$slots, "legend", {}, () => [
|
|
59
|
-
w(y(n.legend), 1)
|
|
60
|
-
])
|
|
61
|
-
]),
|
|
62
|
-
key: "1"
|
|
63
|
-
} : void 0
|
|
64
|
-
]), 1024)) : B("", !0)
|
|
65
|
-
], 8, V)
|
|
66
|
-
]),
|
|
67
|
-
a("div", {
|
|
68
|
-
ref_key: "refContents",
|
|
69
|
-
ref: d,
|
|
70
|
-
class: E(["dwui-accordion-contents", e.expandable ? e.expanded ? "dwui-expanded" : "dwui-shrunk" : ""])
|
|
71
|
-
}, [
|
|
72
|
-
i(t.$slots, "default")
|
|
73
|
-
], 2)
|
|
74
|
-
], 8, T));
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
export {
|
|
78
|
-
G as _
|
|
79
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const e=require("./accordion-fieldset.vue_vue_type_style_index_0_lang-Cod0KnrE.cjs"),_=require("./hourglass-loading.vue_vue_type_style_index_0_lang-C72UVA9W.cjs"),n=require("./label-button.vue_vue_type_script_setup_true_lang-DqhdCgmJ.cjs"),t=require("./label-icon.vue_vue_type_style_index_0_lang-C2URq6GP.cjs"),o=require("./tab-content.vue_vue_type_style_index_0_lang-BeCi7Xkp.cjs"),s=require("./tab-group.vue_vue_type_style_index_0_lang-CwVGYZAo.cjs"),u=Object.freeze(Object.defineProperty({__proto__:null,AccordionFieldset:e._sfc_main,HourglassLoading:_._sfc_main,LabelButton:n._sfc_main,LabelIcon:t._sfc_main,TabContent:o._sfc_main,TabGroup:s._sfc_main},Symbol.toStringTag,{value:"Module"}));exports.components=u;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { _ as o } from "./accordion-fieldset.vue_vue_type_style_index_0_lang-Dk5Id0dl.js";
|
|
2
|
-
import { _ } from "./hourglass-loading.vue_vue_type_style_index_0_lang-DkUGIxQ2.js";
|
|
3
|
-
import { _ as a } from "./label-button.vue_vue_type_script_setup_true_lang-CoHrTUSs.js";
|
|
4
|
-
import { _ as r } from "./label-icon.vue_vue_type_style_index_0_lang-bQFkQ_gC.js";
|
|
5
|
-
import { _ as m } from "./tab-content.vue_vue_type_style_index_0_lang-CcQLHmIF.js";
|
|
6
|
-
import { _ as t } from "./tab-group.vue_vue_type_style_index_0_lang-CjnBkvvZ.js";
|
|
7
|
-
const p = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
8
|
-
__proto__: null,
|
|
9
|
-
AccordionFieldset: o,
|
|
10
|
-
HourglassLoading: _,
|
|
11
|
-
LabelButton: a,
|
|
12
|
-
LabelIcon: r,
|
|
13
|
-
TabContent: m,
|
|
14
|
-
TabGroup: t
|
|
15
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
16
|
-
export {
|
|
17
|
-
p as c
|
|
18
|
-
};
|