@code-coaching/vuetiful 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-coaching/vuetiful",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "scripts": {
5
5
  "dev": "onchange 'src/**/*.vue' 'src/**/*.ts' 'src/**/*.css' -- npm run build",
6
6
  "prebuild": "node 'scripts/intellisense.js'",
@@ -1,4 +1,4 @@
1
1
  import { VButton } from "./atoms";
2
- import { VRail, VRailTile, VShell } from "./molecules";
2
+ import { VDrawer, VRail, VRailTile, VShell } from "./molecules";
3
3
 
4
- export { VButton, VRail, VRailTile, VShell };
4
+ export { VButton, VRail, VRailTile, VShell, VDrawer };
@@ -0,0 +1,97 @@
1
+ <script setup lang="ts">
2
+ import type { CssClasses } from "@/index";
3
+ import { useDrawer } from "@/services";
4
+ import { Ref, computed, onMounted, ref, toRefs, useAttrs } from "vue";
5
+
6
+ const { drawer, close } = useDrawer();
7
+ const attrs = useAttrs();
8
+
9
+ // #region Props
10
+ const props = defineProps({
11
+ position: {
12
+ type: String as () => "left" | "top" | "right" | "bottom",
13
+ default: "left",
14
+ },
15
+ duration: {
16
+ type: Number as () => 150 | 300,
17
+ default: 300,
18
+ },
19
+
20
+ // Regions
21
+ regionBackdrop: {
22
+ type: String as () => CssClasses,
23
+ default: "",
24
+ },
25
+ regionDrawer: {
26
+ type: String as () => CssClasses,
27
+ default: "",
28
+ },
29
+
30
+ // a11y
31
+ labelledby: {
32
+ type: String,
33
+ default: "",
34
+ },
35
+ describedby: {
36
+ type: String,
37
+ default: "",
38
+ },
39
+ });
40
+
41
+ // prettier-ignore
42
+ const { position, duration, regionBackdrop, regionDrawer, labelledby, describedby } = toRefs(props);
43
+ // prettier-ignore
44
+ const presets = {
45
+ top: { alignment: 'top-0', width: 'w-full', height: 'h-[50%]', rounded: 'rounded-bl-container-token rounded-br-container-token' },
46
+ bottom: { alignment: 'bottom-0', width: 'w-full', height: ' h-[50%]', rounded: 'rounded-tl-container-token rounded-tr-container-token' },
47
+ left: { alignment: 'lef-0', width: 'w-[90%]', height: 'h-full', rounded: 'rounded-tr-container-token rounded-br-container-token' },
48
+ right: { alignment: 'right-0', width: 'w-[90%]', height: 'h-full', rounded: 'rounded-tl-container-token rounded-bl-container-token' }
49
+ };
50
+ const preset = computed(() => presets[position.value]);
51
+ // #endregion
52
+
53
+ // #region template refs
54
+ const elemBackdrop: Ref<HTMLElement> = ref() as Ref<HTMLElement>;
55
+ const elemDrawer: Ref<HTMLElement> = ref() as Ref<HTMLElement>;
56
+ // #endregion
57
+
58
+ // #region Event Handlers
59
+ const onBackdropInteraction = (event: Event) => {
60
+ if (event.target === elemBackdrop.value) close();
61
+ };
62
+
63
+ const onKeydownWindow = (event: KeyboardEvent) => {
64
+ if (event.code === "Escape") close();
65
+ };
66
+ onMounted(() => {
67
+ window.addEventListener("keydown", onKeydownWindow);
68
+ });
69
+ // #endregion
70
+ </script>
71
+
72
+ <template>
73
+ <transition :name="`slide-${position}-${duration}`">
74
+ <div
75
+ v-if="drawer.open"
76
+ ref="elemDrawer"
77
+ :class="`drawer absolute overflow-y-auto shadow-xl transition-transform bg-surface-100-800-token ${preset.width} ${preset.height} ${preset.rounded} ${preset.alignment} z-50 ${regionDrawer}`"
78
+ role="dialog"
79
+ aria-modal="true"
80
+ :aria-labelledby="labelledby"
81
+ :aria-describedby="describedby"
82
+ >
83
+ <slot />
84
+ </div>
85
+ </transition>
86
+ <transition :name="`fade-${duration}`">
87
+ <div
88
+ v-if="drawer.open"
89
+ ref="elemBackdrop"
90
+ :class="`drawer-backdrop backdrop-blur-xs fixed top-0 left-0 right-0 bottom-0 flex bg-surface-backdrop-token ${regionBackdrop} z-40 ${
91
+ attrs.class ?? ''
92
+ }`"
93
+ @mousedown="onBackdropInteraction"
94
+ @touchstart="onBackdropInteraction"
95
+ ></div>
96
+ </transition>
97
+ </template>
@@ -37,7 +37,7 @@ const { selectedRailTile } = useRail();
37
37
  const active = inject("active");
38
38
  const hover = inject("hover");
39
39
 
40
- const onClickHandler = (event: MouseEvent) => {
40
+ const onClickHandler = () => {
41
41
  if (!props.value) return;
42
42
  selectedRailTile.value = props.value;
43
43
  emit("click");
@@ -51,10 +51,7 @@ const onKeyHandler = (event: KeyboardEvent) => {
51
51
  </script>
52
52
 
53
53
  <template>
54
- <div
55
- @click="onClickHandler"
56
- @keydown="onKeyHandler"
57
- >
54
+ <div @click="onClickHandler" @keydown="onKeyHandler">
58
55
  <component
59
56
  :is="tag"
60
57
  v-bind="attrs"
@@ -41,7 +41,7 @@ const attrs = useAttrs();
41
41
  v-if="$slots.pageHeader"
42
42
  :class="`vuetiful-page-header flex-none ${slotPageHeader}`"
43
43
  >
44
- <slot name="pageHeader">(slot:header)</slot>
44
+ <slot name="pageHeader" />
45
45
  </header>
46
46
 
47
47
  <main :class="`vuetiful-page-content flex-auto ${slotPageContent}`">
@@ -52,7 +52,7 @@ const attrs = useAttrs();
52
52
  v-if="$slots.pageFooter"
53
53
  :class="`vuetiful-page-footer flex-none ${slotPageFooter}`"
54
54
  >
55
- <slot name="pageFooter">(slot:footer)</slot>
55
+ <slot name="pageFooter" />
56
56
  </footer>
57
57
  </div>
58
58
 
@@ -1,5 +1,6 @@
1
+ import VDrawer from "./VDrawer.vue";
1
2
  import VRail from "./VRail.vue";
2
3
  import VRailTile from "./VRailTile.vue";
3
4
  import VShell from "./VShell.vue";
4
5
 
5
- export { VRail, VRailTile, VShell };
6
+ export { VRail, VRailTile, VShell, VDrawer };
@@ -0,0 +1,43 @@
1
+ import { reactive, readonly } from 'vue';
2
+
3
+ export interface DrawerSettings {
4
+ id?: string;
5
+ open?: boolean;
6
+
7
+ position?: 'left' | 'top' | 'right' | 'bottom';
8
+ duration?: 150 | 300;
9
+
10
+ regionBackdrop?: string;
11
+ regionDrawer?: string;
12
+
13
+ [key: string]: unknown;
14
+ }
15
+
16
+ const drawer = reactive<DrawerSettings>({
17
+ id: 'default',
18
+ open: false,
19
+ });
20
+
21
+ const useDrawer = () => {
22
+ const open = (settings?: DrawerSettings) => {
23
+ drawer.open = true;
24
+ if (settings) {
25
+ Object.keys(settings).forEach((key: string) => {
26
+ drawer[key] = settings[key];
27
+ });
28
+ }
29
+ };
30
+
31
+ const close = () => (drawer.open = false);
32
+
33
+ const toggle = () => (drawer.open = !drawer.open);
34
+
35
+ return {
36
+ drawer: readonly(drawer),
37
+ open,
38
+ close,
39
+ toggle,
40
+ };
41
+ };
42
+
43
+ export { useDrawer };
@@ -1,3 +1,4 @@
1
1
  import { useRail } from "./rail.service";
2
+ import { useDrawer } from "./drawer.service";
2
3
 
3
- export { useRail };
4
+ export { useRail, useDrawer };