@ttdk-design-system/library-vue 0.0.0-stage → 1.0.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/AI_GUIDE.md +6518 -0
- package/llms.txt +6518 -0
- package/package.json +1096 -4
- package/src/core/index.ts +2 -0
- package/src/core/tailwind-preset.cjs +62 -0
- package/src/core/tailwind-preset.ts +85 -0
- package/src/core/theme/tokens.css +663 -0
- package/src/core/types.ts +836 -0
- package/src/index.ts +17 -0
- package/src/tailwind-preset.cjs +62 -0
- package/src/tailwind-preset.ts +85 -0
- package/src/types.ts +1 -0
- package/src/web/accordion/AI_GUIDE.md +149 -0
- package/src/web/accordion/accordion.css +1 -0
- package/src/web/accordion/accordion.vue +432 -0
- package/src/web/accordion/accordion.vue.d.ts +227 -0
- package/src/web/accordion/index.ts +3 -0
- package/src/web/accordion/manifest.json +351 -0
- package/src/web/alert/AI_GUIDE.md +139 -0
- package/src/web/alert/alert.css +1 -0
- package/src/web/alert/alert.vue +290 -0
- package/src/web/alert/alert.vue.d.ts +154 -0
- package/src/web/alert/index.ts +3 -0
- package/src/web/alert/manifest.json +240 -0
- package/src/web/avatar/AI_GUIDE.md +118 -0
- package/src/web/avatar/avatar.css +1 -0
- package/src/web/avatar/avatar.vue +217 -0
- package/src/web/avatar/avatar.vue.d.ts +135 -0
- package/src/web/avatar/index.ts +3 -0
- package/src/web/avatar/manifest.json +195 -0
- package/src/web/badge/AI_GUIDE.md +94 -0
- package/src/web/badge/badge.css +1 -0
- package/src/web/badge/badge.vue +135 -0
- package/src/web/badge/badge.vue.d.ts +108 -0
- package/src/web/badge/index.ts +3 -0
- package/src/web/badge/manifest.json +141 -0
- package/src/web/banner/AI_GUIDE.md +130 -0
- package/src/web/banner/banner.css +1 -0
- package/src/web/banner/banner.vue +303 -0
- package/src/web/banner/banner.vue.d.ts +162 -0
- package/src/web/banner/index.ts +3 -0
- package/src/web/banner/manifest.json +240 -0
- package/src/web/breadcrumb/AI_GUIDE.md +120 -0
- package/src/web/breadcrumb/breadcrumb.css +1 -0
- package/src/web/breadcrumb/breadcrumb.vue +313 -0
- package/src/web/breadcrumb/breadcrumb.vue.d.ts +139 -0
- package/src/web/breadcrumb/index.ts +3 -0
- package/src/web/breadcrumb/manifest.json +225 -0
- package/src/web/button/AI_GUIDE.md +121 -0
- package/src/web/button/button.css +1 -0
- package/src/web/button/button.vue +283 -0
- package/src/web/button/button.vue.d.ts +147 -0
- package/src/web/button/index.ts +3 -0
- package/src/web/button/manifest.json +177 -0
- package/src/web/calendar/AI_GUIDE.md +151 -0
- package/src/web/calendar/calendar.css +1 -0
- package/src/web/calendar/calendar.vue +1536 -0
- package/src/web/calendar/calendar.vue.d.ts +261 -0
- package/src/web/calendar/index.ts +3 -0
- package/src/web/calendar/manifest.json +470 -0
- package/src/web/card/AI_GUIDE.md +133 -0
- package/src/web/card/card.css +1 -0
- package/src/web/card/card.vue +423 -0
- package/src/web/card/card.vue.d.ts +232 -0
- package/src/web/card/index.ts +3 -0
- package/src/web/card/manifest.json +357 -0
- package/src/web/checkbox/AI_GUIDE.md +146 -0
- package/src/web/checkbox/checkbox.css +1 -0
- package/src/web/checkbox/checkbox.vue +304 -0
- package/src/web/checkbox/checkbox.vue.d.ts +189 -0
- package/src/web/checkbox/index.ts +3 -0
- package/src/web/checkbox/manifest.json +294 -0
- package/src/web/chip/AI_GUIDE.md +186 -0
- package/src/web/chip/chip.css +1 -0
- package/src/web/chip/chip.vue +220 -0
- package/src/web/chip/chip.vue.d.ts +140 -0
- package/src/web/chip/index.ts +3 -0
- package/src/web/chip/manifest.json +186 -0
- package/src/web/dropdown/AI_GUIDE.md +167 -0
- package/src/web/dropdown/dropdown.css +1 -0
- package/src/web/dropdown/dropdown.vue +1257 -0
- package/src/web/dropdown/dropdown.vue.d.ts +381 -0
- package/src/web/dropdown/index.ts +3 -0
- package/src/web/dropdown/manifest.json +576 -0
- package/src/web/flex/AI_GUIDE.md +113 -0
- package/src/web/flex/flex-item.vue +94 -0
- package/src/web/flex/flex-item.vue.d.ts +84 -0
- package/src/web/flex/flex.css +1 -0
- package/src/web/flex/flex.vue +103 -0
- package/src/web/flex/flex.vue.d.ts +92 -0
- package/src/web/flex/index.ts +5 -0
- package/src/web/flex/manifest.json +162 -0
- package/src/web/form/index.ts +7 -0
- package/src/web/grid/AI_GUIDE.md +112 -0
- package/src/web/grid/grid-item.vue +109 -0
- package/src/web/grid/grid-item.vue.d.ts +99 -0
- package/src/web/grid/grid.css +1 -0
- package/src/web/grid/grid.vue +94 -0
- package/src/web/grid/grid.vue.d.ts +84 -0
- package/src/web/grid/index.ts +5 -0
- package/src/web/grid/manifest.json +153 -0
- package/src/web/index.ts +86 -0
- package/src/web/input/AI_GUIDE.md +159 -0
- package/src/web/input/index.ts +3 -0
- package/src/web/input/input.css +1 -0
- package/src/web/input/input.vue +521 -0
- package/src/web/input/input.vue.d.ts +274 -0
- package/src/web/input/manifest.json +465 -0
- package/src/web/input-number/AI_GUIDE.md +164 -0
- package/src/web/input-number/index.ts +3 -0
- package/src/web/input-number/input-number.css +1 -0
- package/src/web/input-number/input-number.vue +1153 -0
- package/src/web/input-number/input-number.vue.d.ts +343 -0
- package/src/web/input-number/manifest.json +575 -0
- package/src/web/modal/AI_GUIDE.md +171 -0
- package/src/web/modal/index.ts +3 -0
- package/src/web/modal/manifest.json +375 -0
- package/src/web/modal/modal.css +1 -0
- package/src/web/modal/modal.vue +344 -0
- package/src/web/modal/modal.vue.d.ts +64 -0
- package/src/web/pagination/AI_GUIDE.md +148 -0
- package/src/web/pagination/index.ts +21 -0
- package/src/web/pagination/manifest.json +432 -0
- package/src/web/pagination/pagination-content.vue +42 -0
- package/src/web/pagination/pagination-content.vue.d.ts +28 -0
- package/src/web/pagination/pagination-ellipsis.vue +55 -0
- package/src/web/pagination/pagination-ellipsis.vue.d.ts +28 -0
- package/src/web/pagination/pagination-first.vue +161 -0
- package/src/web/pagination/pagination-first.vue.d.ts +67 -0
- package/src/web/pagination/pagination-item.vue +42 -0
- package/src/web/pagination/pagination-item.vue.d.ts +28 -0
- package/src/web/pagination/pagination-last.vue +161 -0
- package/src/web/pagination/pagination-last.vue.d.ts +67 -0
- package/src/web/pagination/pagination-link.vue +118 -0
- package/src/web/pagination/pagination-link.vue.d.ts +61 -0
- package/src/web/pagination/pagination-next.vue +160 -0
- package/src/web/pagination/pagination-next.vue.d.ts +68 -0
- package/src/web/pagination/pagination-previous.vue +160 -0
- package/src/web/pagination/pagination-previous.vue.d.ts +68 -0
- package/src/web/pagination/pagination.css +1 -0
- package/src/web/pagination/pagination.vue +730 -0
- package/src/web/pagination/pagination.vue.d.ts +247 -0
- package/src/web/popover/AI_GUIDE.md +163 -0
- package/src/web/popover/index.ts +3 -0
- package/src/web/popover/manifest.json +396 -0
- package/src/web/popover/popover.css +1 -0
- package/src/web/popover/popover.vue +579 -0
- package/src/web/popover/popover.vue.d.ts +83 -0
- package/src/web/radio/AI_GUIDE.md +155 -0
- package/src/web/radio/index.ts +3 -0
- package/src/web/radio/manifest.json +294 -0
- package/src/web/radio/radio.css +1 -0
- package/src/web/radio/radio.vue +288 -0
- package/src/web/radio/radio.vue.d.ts +182 -0
- package/src/web/selectbox/AI_GUIDE.md +216 -0
- package/src/web/selectbox/index.ts +3 -0
- package/src/web/selectbox/manifest.json +477 -0
- package/src/web/selectbox/selectbox.css +1 -0
- package/src/web/selectbox/selectbox.vue +1024 -0
- package/src/web/selectbox/selectbox.vue.d.ts +300 -0
- package/src/web/sonner/AI_GUIDE.md +98 -0
- package/src/web/sonner/index.ts +114 -0
- package/src/web/sonner/manifest.json +132 -0
- package/src/web/sonner/sonner.css +1 -0
- package/src/web/sonner/sonner.vue +180 -0
- package/src/web/sonner/sonner.vue.d.ts +113 -0
- package/src/web/table/AI_GUIDE.md +145 -0
- package/src/web/table/index.ts +34 -0
- package/src/web/table/manifest.json +168 -0
- package/src/web/table/table-body.vue +42 -0
- package/src/web/table/table-body.vue.d.ts +28 -0
- package/src/web/table/table-caption.vue +42 -0
- package/src/web/table/table-caption.vue.d.ts +28 -0
- package/src/web/table/table-cell.vue +71 -0
- package/src/web/table/table-cell.vue.d.ts +49 -0
- package/src/web/table/table-empty.vue +105 -0
- package/src/web/table/table-empty.vue.d.ts +57 -0
- package/src/web/table/table-footer.vue +42 -0
- package/src/web/table/table-footer.vue.d.ts +28 -0
- package/src/web/table/table-head.vue +78 -0
- package/src/web/table/table-head.vue.d.ts +50 -0
- package/src/web/table/table-header.vue +42 -0
- package/src/web/table/table-header.vue.d.ts +28 -0
- package/src/web/table/table-row.vue +70 -0
- package/src/web/table/table-row.vue.d.ts +44 -0
- package/src/web/table/table.css +1 -0
- package/src/web/table/table.vue +298 -0
- package/src/web/table/table.vue.d.ts +119 -0
- package/src/web/tabs/AI_GUIDE.md +150 -0
- package/src/web/tabs/index.ts +2 -0
- package/src/web/tabs/manifest.json +315 -0
- package/src/web/tabs/tabs.css +1 -0
- package/src/web/tabs/tabs.vue +164 -0
- package/src/web/tabs/tabs.vue.d.ts +60 -0
- package/src/web/text/AI_GUIDE.md +129 -0
- package/src/web/text/index.ts +2 -0
- package/src/web/text/manifest.json +195 -0
- package/src/web/text/text.css +1 -0
- package/src/web/text/text.vue +195 -0
- package/src/web/text/text.vue.d.ts +161 -0
- package/src/web/textarea/AI_GUIDE.md +141 -0
- package/src/web/textarea/index.ts +3 -0
- package/src/web/textarea/manifest.json +438 -0
- package/src/web/textarea/textarea.css +1 -0
- package/src/web/textarea/textarea.vue +458 -0
- package/src/web/textarea/textarea.vue.d.ts +265 -0
- package/src/web/tooltip/AI_GUIDE.md +110 -0
- package/src/web/tooltip/index.ts +3 -0
- package/src/web/tooltip/manifest.json +222 -0
- package/src/web/tooltip/tooltip.css +1 -0
- package/src/web/tooltip/tooltip.vue +417 -0
- package/src/web/tooltip/tooltip.vue.d.ts +150 -0
- package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
- package/src/webview/bottomsheet/bottomsheet.css +1 -0
- package/src/webview/bottomsheet/bottomsheet.vue +441 -0
- package/src/webview/bottomsheet/bottomsheet.vue.d.ts +178 -0
- package/src/webview/bottomsheet/index.ts +4 -0
- package/src/webview/bottomsheet/manifest.json +377 -0
- package/src/webview/button/AI_GUIDE.md +79 -0
- package/src/webview/button/button-ios.css +1 -0
- package/src/webview/button/button-ios.vue +138 -0
- package/src/webview/button/button-ios.vue.d.ts +102 -0
- package/src/webview/button/button-material.css +1 -0
- package/src/webview/button/button-material.vue +138 -0
- package/src/webview/button/button-material.vue.d.ts +102 -0
- package/src/webview/button/index.ts +7 -0
- package/src/webview/button/manifest.json +148 -0
- package/src/webview/index.ts +7 -0
- package/tailwind-preset.cjs +62 -0
- package/tailwind-preset.js +62 -0
- package/ttdk-manifest.json +10188 -0
- package/README.md +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.ttdk-bottomsheet-portal{z-index:1000;pointer-events:none;font-family:var(--ttdk-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);flex-direction:column;justify-content:flex-end;display:flex;position:fixed;inset:0}.ttdk-bottomsheet-overlay{z-index:1000;pointer-events:auto;background-color:var(--ttdk-bg-overlay,#14131380);animation:.25s ease-out forwards ttdk-bottomsheet-fade-in;position:fixed;inset:0}.ttdk-bottomsheet-portal[data-mode=ios] .ttdk-bottomsheet-overlay{-webkit-backdrop-filter:blur(8px)}.ttdk-bottomsheet-sheet{z-index:1001;pointer-events:auto;background-color:var(--ttdk-bg-base-primary,#fff);width:100%;color:var(--ttdk-text-icon-primary,#141313);box-shadow:var(--ttdk-shadow-lg,0px -4px 20px #00000026);box-sizing:border-box;padding-bottom:max(16px, env(safe-area-inset-bottom,16px));border-top-left-radius:20px;border-top-right-radius:20px;flex-direction:column;transition:transform .25s cubic-bezier(.16,1,.3,1);animation:.32s cubic-bezier(.16,1,.3,1) forwards ttdk-bottomsheet-slide-up;display:flex;position:relative;overflow:hidden}.ttdk-bottomsheet-sheet.ttdk-bottomsheet-anim-done{animation:none!important}.ttdk-bottomsheet-sheet[data-dragging=true]{cursor:grabbing!important;transition:none!important;animation:none!important}.ttdk-bottomsheet-sheet[data-dragging=true] *{-webkit-user-select:none!important;user-select:none!important}.ttdk-bottomsheet-sheet.ttdk-bottomsheet-closing{transition:transform .22s cubic-bezier(.16,1,.3,1)!important;animation:none!important;transform:translateY(100%)!important}.ttdk-bottomsheet-portal.ttdk-bottomsheet-closing .ttdk-bottomsheet-overlay{opacity:0;transition:opacity .2s ease-out}.ttdk-bottomsheet-sheet[data-mode=ios]{border-top-left-radius:22px;border-top-right-radius:22px}.ttdk-bottomsheet-sheet[data-mode=material]{border-top-left-radius:28px;border-top-right-radius:28px;box-shadow:0 8px 36px #0000003d}.ttdk-bottomsheet-sheet[data-height=auto]{max-height:90vh}.ttdk-bottomsheet-sheet[data-height=sm]{height:35vh;max-height:40vh}.ttdk-bottomsheet-sheet[data-height=md]{height:55vh;max-height:60vh}.ttdk-bottomsheet-sheet[data-height=lg]{height:85vh;max-height:90vh}.ttdk-bottomsheet-sheet[data-height=full]{border-top-left-radius:0;border-top-right-radius:0;height:100vh;max-height:100vh}.ttdk-bottomsheet-handle-wrapper{cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;width:100%;padding-top:12px;padding-bottom:8px;display:flex}.ttdk-bottomsheet-handle-wrapper:active,.ttdk-bottomsheet-sheet[data-dragging=true] .ttdk-bottomsheet-handle-wrapper{cursor:grabbing}.ttdk-bottomsheet-handle{background-color:var(--ttdk-border-subtle,#d1d5db);border-radius:9999px;width:36px;height:4.5px;transition:background-color .2s,transform .15s}.ttdk-bottomsheet-handle-wrapper:active .ttdk-bottomsheet-handle,.ttdk-bottomsheet-sheet[data-dragging=true] .ttdk-bottomsheet-handle{background-color:var(--ttdk-color-neutral-400,#9ca3af);transform:scaleX(1.15)}.ttdk-bottomsheet-sheet[data-mode=material] .ttdk-bottomsheet-handle{width:32px;height:4px}.ttdk-bottomsheet-header{touch-action:none;-webkit-user-select:none;user-select:none;cursor:grab;border-bottom:1px solid #0000;justify-content:space-between;align-items:flex-start;gap:16px;padding:8px 20px 12px;display:flex}.ttdk-bottomsheet-header:active,.ttdk-bottomsheet-sheet[data-dragging=true] .ttdk-bottomsheet-header{cursor:grabbing}.ttdk-bottomsheet-header-info{flex:1;min-width:0}.ttdk-bottomsheet-title{color:var(--ttdk-text-icon-primary,#141313);margin:0;font-size:18px;font-weight:600;line-height:1.4}.ttdk-bottomsheet-description{color:var(--ttdk-text-icon-secondary,#6b7280);margin:4px 0 0;font-size:14px;line-height:1.45}.ttdk-bottomsheet-close{width:32px;height:32px;color:var(--ttdk-text-icon-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:9999px;flex-shrink:0;justify-content:center;align-items:center;padding:0;transition:background-color .15s,color .15s;display:inline-flex}.ttdk-bottomsheet-close svg{stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.ttdk-bottomsheet-close:hover{background-color:var(--ttdk-bg-secondary-hover,#0000000d);color:var(--ttdk-text-icon-primary,#141313)}.ttdk-bottomsheet-close:active{background-color:var(--ttdk-bg-secondary-active,#0000001a)}.ttdk-bottomsheet-body{-webkit-overflow-scrolling:touch;color:var(--ttdk-text-icon-primary,#141313);flex:auto;padding:8px 20px 16px;font-size:15px;line-height:1.5;overflow-y:auto}.ttdk-bottomsheet-footer{border-top:1px solid var(--ttdk-border-subtle,#f3f4f6);flex-shrink:0;align-items:center;gap:12px;padding:12px 20px 0;display:flex}.ttdk-bottomsheet-shake{animation:.35s ease-in-out ttdk-bottomsheet-bounce}.dark .ttdk-bottomsheet-sheet,[data-theme=dark] .ttdk-bottomsheet-sheet{background-color:var(--ttdk-bg-base-primary,#18181b);color:var(--ttdk-text-icon-primary,#f4f4f5);box-shadow:0 -4px 24px #00000073}.dark .ttdk-bottomsheet-handle,[data-theme=dark] .ttdk-bottomsheet-handle{background-color:var(--ttdk-border-subtle,#3f3f46)}.dark .ttdk-bottomsheet-title,[data-theme=dark] .ttdk-bottomsheet-title{color:var(--ttdk-text-icon-primary,#f4f4f5)}.dark .ttdk-bottomsheet-description,[data-theme=dark] .ttdk-bottomsheet-description{color:var(--ttdk-text-icon-secondary,#a1a1aa)}.dark .ttdk-bottomsheet-body,[data-theme=dark] .ttdk-bottomsheet-body{color:var(--ttdk-text-icon-primary,#f4f4f5)}.dark .ttdk-bottomsheet-footer,[data-theme=dark] .ttdk-bottomsheet-footer{border-top-color:var(--ttdk-border-subtle,#27272a)}.dark .ttdk-bottomsheet-close:hover,[data-theme=dark] .ttdk-bottomsheet-close:hover{color:#f4f4f5;background-color:#ffffff14}@keyframes ttdk-bottomsheet-fade-in{0%{opacity:0}to{opacity:1}}@keyframes ttdk-bottomsheet-slide-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes ttdk-bottomsheet-bounce{0%,to{transform:translateY(0)}30%{transform:translateY(-8px)}60%{transform:translateY(-2px)}}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Teleport to="body">
|
|
3
|
+
<div
|
|
4
|
+
v-if="isOpen || isClosing"
|
|
5
|
+
ref="rootRef"
|
|
6
|
+
role="dialog"
|
|
7
|
+
aria-modal="true"
|
|
8
|
+
:class="['ttdk-bottomsheet-portal', isClosing ? 'ttdk-bottomsheet-closing' : '', className || '', $attrs.class]"
|
|
9
|
+
:data-mode="mode || 'auto'"
|
|
10
|
+
:tabIndex="-1"
|
|
11
|
+
:style="{
|
|
12
|
+
...buildUiVars(ui),
|
|
13
|
+
...(typeof style === 'object' ? style : {}),
|
|
14
|
+
}"
|
|
15
|
+
>
|
|
16
|
+
<!-- Backdrop Overlay -->
|
|
17
|
+
<div
|
|
18
|
+
v-if="overlay !== false"
|
|
19
|
+
:class="['ttdk-bottomsheet-overlay', overlayClass || '']"
|
|
20
|
+
:style="{
|
|
21
|
+
opacity: isDragging && dragOffset > 0 ? Math.max(0.15, 1 - dragOffset / 350) : undefined,
|
|
22
|
+
...buildUiVars(overlayStyle),
|
|
23
|
+
}"
|
|
24
|
+
@click="handleOverlayClick"
|
|
25
|
+
/>
|
|
26
|
+
|
|
27
|
+
<!-- Bottom Sheet Card -->
|
|
28
|
+
<div
|
|
29
|
+
ref="sheetRef"
|
|
30
|
+
:class="[
|
|
31
|
+
'ttdk-bottomsheet-sheet',
|
|
32
|
+
isAnimDone ? 'ttdk-bottomsheet-anim-done' : '',
|
|
33
|
+
isClosing ? 'ttdk-bottomsheet-closing' : '',
|
|
34
|
+
isShaking ? 'ttdk-bottomsheet-shake' : '',
|
|
35
|
+
contentClass || ''
|
|
36
|
+
].filter(Boolean).join(' ').trim()"
|
|
37
|
+
:data-height="height || 'auto'"
|
|
38
|
+
:data-mode="mode || 'auto'"
|
|
39
|
+
:data-dragging="isDragging ? 'true' : undefined"
|
|
40
|
+
:style="{
|
|
41
|
+
maxHeight: maxHeight || undefined,
|
|
42
|
+
transform: isClosing
|
|
43
|
+
? 'translateY(100%)'
|
|
44
|
+
: isDragging && dragOffset !== 0
|
|
45
|
+
? 'translateY(' + Math.max(0, dragOffset) + 'px)'
|
|
46
|
+
: undefined,
|
|
47
|
+
...buildUiVars(contentStyle),
|
|
48
|
+
}"
|
|
49
|
+
>
|
|
50
|
+
<!-- Drag Handle Indicator -->
|
|
51
|
+
<div
|
|
52
|
+
v-if="handle !== false"
|
|
53
|
+
:class="['ttdk-bottomsheet-handle-wrapper', handleClass || '']"
|
|
54
|
+
:style="{
|
|
55
|
+
...buildUiVars(handleStyle),
|
|
56
|
+
}"
|
|
57
|
+
@pointerdown="handleDragStart"
|
|
58
|
+
@pointermove="handleDragMove"
|
|
59
|
+
@pointerup="handleDragEnd"
|
|
60
|
+
@touchstart="handleDragStart"
|
|
61
|
+
@touchmove="handleDragMove"
|
|
62
|
+
@touchend="handleDragEnd"
|
|
63
|
+
>
|
|
64
|
+
<div class="ttdk-bottomsheet-handle" aria-hidden="true" />
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- Custom Content Override Slot -->
|
|
68
|
+
<slot name="content" :close="() => closeSheet(true)">
|
|
69
|
+
<!-- Header -->
|
|
70
|
+
<div
|
|
71
|
+
v-if="hasHeader"
|
|
72
|
+
:class="['ttdk-bottomsheet-header', headerClass || '']"
|
|
73
|
+
:style="{
|
|
74
|
+
...buildUiVars(headerStyle),
|
|
75
|
+
}"
|
|
76
|
+
@pointerdown="handleDragStart"
|
|
77
|
+
@pointermove="handleDragMove"
|
|
78
|
+
@pointerup="handleDragEnd"
|
|
79
|
+
@touchstart="handleDragStart"
|
|
80
|
+
@touchmove="handleDragMove"
|
|
81
|
+
@touchend="handleDragEnd"
|
|
82
|
+
>
|
|
83
|
+
<slot name="header" :close="() => closeSheet(true)">
|
|
84
|
+
<div class="ttdk-bottomsheet-header-info">
|
|
85
|
+
<h3 v-if="title" class="ttdk-bottomsheet-title">{{ title }}</h3>
|
|
86
|
+
<p v-if="description" class="ttdk-bottomsheet-description">{{ description }}</p>
|
|
87
|
+
</div>
|
|
88
|
+
<button
|
|
89
|
+
v-if="close"
|
|
90
|
+
type="button"
|
|
91
|
+
class="ttdk-bottomsheet-close"
|
|
92
|
+
aria-label="Tutup lembar"
|
|
93
|
+
@click.stop="() => closeSheet(true)"
|
|
94
|
+
>
|
|
95
|
+
<slot name="close-icon">
|
|
96
|
+
<component :is="closeIcon" v-if="closeIcon" />
|
|
97
|
+
<svg
|
|
98
|
+
v-else
|
|
99
|
+
width="18"
|
|
100
|
+
height="18"
|
|
101
|
+
viewBox="0 0 24 24"
|
|
102
|
+
fill="none"
|
|
103
|
+
stroke="currentColor"
|
|
104
|
+
stroke-width="2"
|
|
105
|
+
stroke-linecap="round"
|
|
106
|
+
stroke-linejoin="round"
|
|
107
|
+
>
|
|
108
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
109
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
110
|
+
</svg>
|
|
111
|
+
</slot>
|
|
112
|
+
</button>
|
|
113
|
+
</slot>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<!-- Body -->
|
|
117
|
+
<div
|
|
118
|
+
:class="['ttdk-bottomsheet-body', bodyClass || '']"
|
|
119
|
+
:style="{
|
|
120
|
+
...buildUiVars(bodyStyle),
|
|
121
|
+
}"
|
|
122
|
+
>
|
|
123
|
+
<slot :close="() => closeSheet(true)">
|
|
124
|
+
<component :is="body" v-if="body" :close="() => closeSheet(true)" />
|
|
125
|
+
</slot>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<!-- Footer -->
|
|
129
|
+
<div
|
|
130
|
+
v-if="hasFooter"
|
|
131
|
+
:class="['ttdk-bottomsheet-footer', footerClass || '']"
|
|
132
|
+
:style="{
|
|
133
|
+
...buildUiVars(footerStyle),
|
|
134
|
+
}"
|
|
135
|
+
>
|
|
136
|
+
<slot name="footer" :close="() => closeSheet(true)">
|
|
137
|
+
<component :is="footer" v-if="footer" :close="() => closeSheet(true)" />
|
|
138
|
+
</slot>
|
|
139
|
+
</div>
|
|
140
|
+
</slot>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</Teleport>
|
|
144
|
+
</template>
|
|
145
|
+
|
|
146
|
+
<script setup lang="ts">
|
|
147
|
+
import { ref, computed, watch, onMounted, onUnmounted, useSlots } from "vue";
|
|
148
|
+
import { buildUiVars, UiProps } from "../../core/types";
|
|
149
|
+
import "./bottomsheet.css";
|
|
150
|
+
|
|
151
|
+
export type BottomSheetHeight = 'auto' | 'sm' | 'md' | 'lg' | 'full';
|
|
152
|
+
export type BottomSheetMode = 'auto' | 'ios' | 'material';
|
|
153
|
+
export type BottomSheetUiProps = UiProps;
|
|
154
|
+
|
|
155
|
+
export interface BottomSheetProps {
|
|
156
|
+
open?: boolean;
|
|
157
|
+
defaultOpen?: boolean;
|
|
158
|
+
title?: string;
|
|
159
|
+
description?: string;
|
|
160
|
+
height?: BottomSheetHeight;
|
|
161
|
+
maxHeight?: string;
|
|
162
|
+
mode?: BottomSheetMode;
|
|
163
|
+
handle?: boolean;
|
|
164
|
+
swipeable?: boolean;
|
|
165
|
+
close?: boolean;
|
|
166
|
+
closeIcon?: any;
|
|
167
|
+
dismissible?: boolean;
|
|
168
|
+
preventClose?: boolean;
|
|
169
|
+
overlay?: boolean;
|
|
170
|
+
preventScroll?: boolean;
|
|
171
|
+
header?: any;
|
|
172
|
+
body?: any;
|
|
173
|
+
footer?: any;
|
|
174
|
+
content?: any;
|
|
175
|
+
ui?: BottomSheetUiProps;
|
|
176
|
+
className?: string;
|
|
177
|
+
class?: string;
|
|
178
|
+
style?: any;
|
|
179
|
+
overlayClass?: string;
|
|
180
|
+
overlayStyle?: any;
|
|
181
|
+
contentClass?: string;
|
|
182
|
+
contentStyle?: any;
|
|
183
|
+
headerClass?: string;
|
|
184
|
+
headerStyle?: any;
|
|
185
|
+
bodyClass?: string;
|
|
186
|
+
bodyStyle?: any;
|
|
187
|
+
footerClass?: string;
|
|
188
|
+
footerStyle?: any;
|
|
189
|
+
handleClass?: string;
|
|
190
|
+
handleStyle?: any;
|
|
191
|
+
onOpenChange?: (open: boolean) => void;
|
|
192
|
+
onUpdateOpen?: (open: boolean) => void;
|
|
193
|
+
onOpen?: () => void;
|
|
194
|
+
onClose?: () => void;
|
|
195
|
+
onClosePrevent?: () => void;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const props = withDefaults(defineProps<BottomSheetProps>(), {
|
|
199
|
+
defaultOpen: false,
|
|
200
|
+
height: "auto",
|
|
201
|
+
mode: "auto",
|
|
202
|
+
handle: true,
|
|
203
|
+
swipeable: true,
|
|
204
|
+
close: false,
|
|
205
|
+
dismissible: true,
|
|
206
|
+
preventClose: false,
|
|
207
|
+
overlay: true,
|
|
208
|
+
preventScroll: true,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const emit = defineEmits<{
|
|
212
|
+
(e: "update:open", value: boolean): void;
|
|
213
|
+
(e: "update:modelValue", value: boolean): void;
|
|
214
|
+
(e: "open"): void;
|
|
215
|
+
(e: "close"): void;
|
|
216
|
+
(e: "close:prevent"): void;
|
|
217
|
+
}>();
|
|
218
|
+
|
|
219
|
+
const slots = useSlots();
|
|
220
|
+
const rootRef = ref<HTMLElement | null>(null);
|
|
221
|
+
const sheetRef = ref<HTMLElement | null>(null);
|
|
222
|
+
|
|
223
|
+
const isOpen = ref(props.open !== undefined ? props.open : props.defaultOpen);
|
|
224
|
+
const isClosing = ref(false);
|
|
225
|
+
const isDragging = ref(false);
|
|
226
|
+
const dragOffset = ref(0);
|
|
227
|
+
const touchStartY = ref(0);
|
|
228
|
+
const isAnimDone = ref(false);
|
|
229
|
+
const isShaking = ref(false);
|
|
230
|
+
let shakeTimer: any = null;
|
|
231
|
+
let animTimer: any = null;
|
|
232
|
+
|
|
233
|
+
const hasHeader = computed(() => {
|
|
234
|
+
return Boolean(slots.header || props.header || props.title || props.description || props.close);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const hasFooter = computed(() => {
|
|
238
|
+
return Boolean(slots.footer || props.footer);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
let lockCount = 0;
|
|
242
|
+
let originalOverflow = "";
|
|
243
|
+
let originalPaddingRight = "";
|
|
244
|
+
|
|
245
|
+
function lockBodyScroll() {
|
|
246
|
+
if (typeof document === "undefined") return;
|
|
247
|
+
if (lockCount === 0) {
|
|
248
|
+
originalOverflow = document.body.style.overflow;
|
|
249
|
+
originalPaddingRight = document.body.style.paddingRight;
|
|
250
|
+
const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
251
|
+
document.body.style.overflow = "hidden";
|
|
252
|
+
if (scrollBarWidth > 0) {
|
|
253
|
+
document.body.style.paddingRight = scrollBarWidth + "px";
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
lockCount++;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function unlockBodyScroll() {
|
|
260
|
+
if (typeof document === "undefined") return;
|
|
261
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
262
|
+
if (lockCount === 0) {
|
|
263
|
+
document.body.style.overflow = originalOverflow;
|
|
264
|
+
document.body.style.paddingRight = originalPaddingRight;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let isScrollLocked = false;
|
|
269
|
+
function applyScrollLock(shouldLock: boolean) {
|
|
270
|
+
if (shouldLock && !isScrollLocked) {
|
|
271
|
+
lockBodyScroll();
|
|
272
|
+
isScrollLocked = true;
|
|
273
|
+
} else if (!shouldLock && isScrollLocked) {
|
|
274
|
+
unlockBodyScroll();
|
|
275
|
+
isScrollLocked = false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function isDismissible() {
|
|
280
|
+
if (props.preventClose === true) return false;
|
|
281
|
+
return props.dismissible !== false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function triggerShake() {
|
|
285
|
+
if (shakeTimer) clearTimeout(shakeTimer);
|
|
286
|
+
isAnimDone.value = true;
|
|
287
|
+
isShaking.value = true;
|
|
288
|
+
shakeTimer = setTimeout(() => {
|
|
289
|
+
isShaking.value = false;
|
|
290
|
+
shakeTimer = null;
|
|
291
|
+
}, 400);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function openSheet() {
|
|
295
|
+
if (!isOpen.value) {
|
|
296
|
+
isOpen.value = true;
|
|
297
|
+
isClosing.value = false;
|
|
298
|
+
isAnimDone.value = false;
|
|
299
|
+
if (animTimer) clearTimeout(animTimer);
|
|
300
|
+
animTimer = setTimeout(() => {
|
|
301
|
+
isAnimDone.value = true;
|
|
302
|
+
}, 300);
|
|
303
|
+
emit("update:open", true);
|
|
304
|
+
emit("update:modelValue", true);
|
|
305
|
+
emit("open");
|
|
306
|
+
if (props.onOpen) props.onOpen();
|
|
307
|
+
if (props.onUpdateOpen) props.onUpdateOpen(true);
|
|
308
|
+
if (props.onOpenChange) props.onOpenChange(true);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function closeSheet(force?: boolean) {
|
|
313
|
+
if (!isDismissible() && !force) {
|
|
314
|
+
triggerShake();
|
|
315
|
+
emit("close:prevent");
|
|
316
|
+
if (props.onClosePrevent) props.onClosePrevent();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (isOpen.value) {
|
|
320
|
+
isOpen.value = false;
|
|
321
|
+
isAnimDone.value = false;
|
|
322
|
+
isClosing.value = false;
|
|
323
|
+
emit("update:open", false);
|
|
324
|
+
emit("update:modelValue", false);
|
|
325
|
+
emit("close");
|
|
326
|
+
if (props.onClose) props.onClose();
|
|
327
|
+
if (props.onUpdateOpen) props.onUpdateOpen(false);
|
|
328
|
+
if (props.onOpenChange) props.onOpenChange(false);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function handleOverlayClick() {
|
|
333
|
+
closeSheet();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
337
|
+
if (!isOpen.value) return;
|
|
338
|
+
if (event.key === "Escape") {
|
|
339
|
+
closeSheet();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function handleDragStart(event: any) {
|
|
344
|
+
if (props.swipeable === false) return;
|
|
345
|
+
if (event.button !== undefined && event.button !== 0) return;
|
|
346
|
+
if (event.target && event.target.closest && event.target.closest("button, a, input, select, textarea")) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const clientY = event.clientY !== undefined ? event.clientY : (event.touches && event.touches[0] ? event.touches[0].clientY : 0);
|
|
350
|
+
touchStartY.value = clientY;
|
|
351
|
+
isDragging.value = true;
|
|
352
|
+
dragOffset.value = 0;
|
|
353
|
+
if (event.currentTarget && typeof event.currentTarget.setPointerCapture === "function" && event.pointerId !== undefined) {
|
|
354
|
+
try {
|
|
355
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
356
|
+
} catch (_) {}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function handleDragMove(event: any) {
|
|
361
|
+
if (!isDragging.value) return;
|
|
362
|
+
const clientY = event.clientY !== undefined ? event.clientY : (event.touches && event.touches[0] ? event.touches[0].clientY : 0);
|
|
363
|
+
const delta = clientY - touchStartY.value;
|
|
364
|
+
if (delta > 0) {
|
|
365
|
+
dragOffset.value = delta;
|
|
366
|
+
} else {
|
|
367
|
+
dragOffset.value = delta * 0.2;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function handleDragEnd(event?: any) {
|
|
372
|
+
if (!isDragging.value) return;
|
|
373
|
+
isDragging.value = false;
|
|
374
|
+
if (event && event.currentTarget && typeof event.currentTarget.releasePointerCapture === "function" && event.pointerId !== undefined) {
|
|
375
|
+
try {
|
|
376
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
377
|
+
} catch (_) {}
|
|
378
|
+
}
|
|
379
|
+
const currentOffset = dragOffset.value;
|
|
380
|
+
if (currentOffset > 70) {
|
|
381
|
+
isClosing.value = true;
|
|
382
|
+
setTimeout(() => {
|
|
383
|
+
isClosing.value = false;
|
|
384
|
+
dragOffset.value = 0;
|
|
385
|
+
closeSheet(true);
|
|
386
|
+
}, 220);
|
|
387
|
+
} else {
|
|
388
|
+
dragOffset.value = 0;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function onWindowPointerMove(e: PointerEvent) {
|
|
393
|
+
if (isDragging.value) handleDragMove(e);
|
|
394
|
+
}
|
|
395
|
+
function onWindowPointerUp(e: PointerEvent) {
|
|
396
|
+
if (isDragging.value) handleDragEnd(e);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
watch(
|
|
400
|
+
() => props.open,
|
|
401
|
+
(val) => {
|
|
402
|
+
if (val !== undefined && val !== isOpen.value) {
|
|
403
|
+
if (val) {
|
|
404
|
+
openSheet();
|
|
405
|
+
} else {
|
|
406
|
+
closeSheet(true);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
watch(
|
|
413
|
+
isOpen,
|
|
414
|
+
(val) => {
|
|
415
|
+
applyScrollLock(val && props.preventScroll !== false);
|
|
416
|
+
},
|
|
417
|
+
{ immediate: true }
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
onMounted(() => {
|
|
421
|
+
if (isOpen.value) {
|
|
422
|
+
applyScrollLock(props.preventScroll !== false);
|
|
423
|
+
}
|
|
424
|
+
if (typeof document !== "undefined") {
|
|
425
|
+
document.addEventListener("keydown", handleKeyDown, true);
|
|
426
|
+
window.addEventListener("pointermove", onWindowPointerMove);
|
|
427
|
+
window.addEventListener("pointerup", onWindowPointerUp);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
onUnmounted(() => {
|
|
432
|
+
applyScrollLock(false);
|
|
433
|
+
if (shakeTimer) clearTimeout(shakeTimer);
|
|
434
|
+
if (animTimer) clearTimeout(animTimer);
|
|
435
|
+
if (typeof document !== "undefined") {
|
|
436
|
+
document.removeEventListener("keydown", handleKeyDown, true);
|
|
437
|
+
window.removeEventListener("pointermove", onWindowPointerMove);
|
|
438
|
+
window.removeEventListener("pointerup", onWindowPointerUp);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
</script>
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Auto-generated by TTDK Design System Vue Type Generator
|
|
3
|
+
import type { DefineComponent } from "vue";
|
|
4
|
+
import { buildUiVars, UiProps } from "../../core/types";
|
|
5
|
+
|
|
6
|
+
export type BottomSheetHeight = "auto" | "sm" | "md" | "lg" | "full";
|
|
7
|
+
|
|
8
|
+
export type BottomSheetMode = "auto" | "ios" | "material";
|
|
9
|
+
|
|
10
|
+
export type BottomSheetUiProps = UiProps;
|
|
11
|
+
|
|
12
|
+
export interface BottomSheetProps {
|
|
13
|
+
/**
|
|
14
|
+
* Status visibilitas bottom sheet (mode controlled).
|
|
15
|
+
* Mendukung `v-model:open` / `v-model` pada Vue dan controlled prop `open` pada React.
|
|
16
|
+
*/
|
|
17
|
+
open?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Status visibilitas awal bottom sheet saat pertama kali dimuat (uncontrolled initial state).
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
defaultOpen?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Judul teks di bagian header bottom sheet.
|
|
27
|
+
*/
|
|
28
|
+
title?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Deskripsi penjelasan di bagian header di bawah judul.
|
|
32
|
+
*/
|
|
33
|
+
description?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Skala ukuran tinggi bottom sheet:
|
|
37
|
+
* - `'auto'`: Menyesuaikan tinggi isi konten (maksimal 90vh).
|
|
38
|
+
* - `'sm'`: Lembar ringkas (~35% tinggi layar).
|
|
39
|
+
* - `'md'`: Lembar proporsional standar (~55% tinggi layar).
|
|
40
|
+
* - `'lg'`: Lembar luas (~85% tinggi layar).
|
|
41
|
+
* - `'full'`: Tampilan penuh (100% tinggi layar).
|
|
42
|
+
* @default 'auto'
|
|
43
|
+
*/
|
|
44
|
+
height?: BottomSheetHeight;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Batas tinggi maksimum lembar sheet (contoh: '90vh', '600px').
|
|
48
|
+
*/
|
|
49
|
+
maxHeight?: string;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cita rasa / gaya platform mobile:
|
|
53
|
+
* - `'auto'`: Desain netral adaptif khas TTDK Design System.
|
|
54
|
+
* - `'ios'`: Cita rasa Apple Human Interface (frosted glass, sudut kurva halus 20px).
|
|
55
|
+
* - `'material'`: Cita rasa Material Design 3 (sudut 28px, elevated shadow).
|
|
56
|
+
* @default 'auto'
|
|
57
|
+
*/
|
|
58
|
+
mode?: BottomSheetMode;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Menampilkan bilah pegangan geser (drag handle indicator) di bagian atas lembar.
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
handle?: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Mengaktifkan gestur sentuh geser ke bawah (swipe-down) untuk menutup lembar.
|
|
68
|
+
* @default true
|
|
69
|
+
*/
|
|
70
|
+
swipeable?: boolean;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Menampilkan tombol tutup 'X' di pojok kanan atas header.
|
|
74
|
+
* @default false
|
|
75
|
+
*/
|
|
76
|
+
close?: boolean;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Ikon kustom untuk tombol tutup.
|
|
80
|
+
*/
|
|
81
|
+
closeIcon?: any;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Mengizinkan lembar ditutup saat pengguna mengeklik backdrop overlay atau menekan tombol Escape.
|
|
85
|
+
* @default true
|
|
86
|
+
*/
|
|
87
|
+
dismissible?: boolean;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Mencegah lembar ditutup saat klik di luar atau saat digeser (prevent close).
|
|
91
|
+
* Jika bernilai `true`, lembar hanya dapat ditutup via aksi eksplisit.
|
|
92
|
+
* @default false
|
|
93
|
+
*/
|
|
94
|
+
preventClose?: boolean;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Menampilkan lapisan latar belakang redup (backdrop overlay).
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
overlay?: boolean;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Mengunci scrolling pada halaman web di latar belakang saat lembar terbuka (body scroll lock).
|
|
104
|
+
* @default true
|
|
105
|
+
*/
|
|
106
|
+
preventScroll?: boolean;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Konten kustom untuk bagian header lembar.
|
|
110
|
+
*/
|
|
111
|
+
header?: any;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Konten kustom untuk bagian isi utama (body) lembar.
|
|
115
|
+
*/
|
|
116
|
+
body?: any;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Konten kustom untuk bagian footer aksi di bawah lembar (misal: tombol konfirmasi / CTA).
|
|
120
|
+
*/
|
|
121
|
+
footer?: any;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Penggantian seluruh konten lembar (mengabaikan layout header, body, footer bawaan).
|
|
125
|
+
*/
|
|
126
|
+
content?: any;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Konten utama lembar bottom sheet (body content).
|
|
130
|
+
*/
|
|
131
|
+
children?: any;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Callback event saat status terbuka/tertutup berubah (standar React).
|
|
135
|
+
*/
|
|
136
|
+
onOpenChange?: (open: boolean) => void;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Callback event saat status terbuka/tertutup berubah untuk two-way binding `v-model:open` (Vue).
|
|
140
|
+
*/
|
|
141
|
+
onUpdateOpen?: (open: boolean) => void;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Callback event saat lembar bottom sheet terbuka.
|
|
145
|
+
*/
|
|
146
|
+
onOpen?: () => void;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Callback event saat lembar bottom sheet ditutup.
|
|
150
|
+
*/
|
|
151
|
+
onClose?: () => void;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Callback event saat pengguna mencoba menutup lembar tetapi dicegah karena `preventClose={true}`.
|
|
155
|
+
*/
|
|
156
|
+
onClosePrevent?: () => void;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Kustomisasi visual granular pada elemen root melalui style-like object.
|
|
160
|
+
*/
|
|
161
|
+
ui?: BottomSheetUiProps;
|
|
162
|
+
className?: string;
|
|
163
|
+
overlayClass?: string;
|
|
164
|
+
overlayStyle?: any;
|
|
165
|
+
contentClass?: string;
|
|
166
|
+
contentStyle?: any;
|
|
167
|
+
headerClass?: string;
|
|
168
|
+
headerStyle?: any;
|
|
169
|
+
bodyClass?: string;
|
|
170
|
+
bodyStyle?: any;
|
|
171
|
+
footerClass?: string;
|
|
172
|
+
footerStyle?: any;
|
|
173
|
+
handleClass?: string;
|
|
174
|
+
handleStyle?: any;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
declare const component: DefineComponent<BottomSheetProps>;
|
|
178
|
+
export default component;
|