@toife/vue 3.1.4 → 3.1.5

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.
Files changed (92) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/components/action/action.scss +1 -1
  4. package/src/components/action/action.vue +5 -5
  5. package/src/components/app/app.scss +2 -2
  6. package/src/components/app/app.vue +5 -5
  7. package/src/components/avatar/avatar.scss +3 -2
  8. package/src/components/avatar/avatar.vue +6 -6
  9. package/src/components/button/button.scss +13 -13
  10. package/src/components/button/button.vue +7 -7
  11. package/src/components/cable/cable.vue +2 -2
  12. package/src/components/card/card/card.scss +2 -2
  13. package/src/components/card/card/card.vue +5 -5
  14. package/src/components/card/card-body/card-body.scss +2 -2
  15. package/src/components/card/card-body/card-body.vue +2 -2
  16. package/src/components/card/card-footer/card-footer.scss +3 -3
  17. package/src/components/card/card-footer/card-footer.vue +2 -2
  18. package/src/components/card/card-header/card-header.scss +3 -3
  19. package/src/components/card/card-header/card-header.vue +2 -2
  20. package/src/components/checkbox/checkbox.html +1 -1
  21. package/src/components/checkbox/checkbox.scss +18 -13
  22. package/src/components/checkbox/checkbox.vue +7 -7
  23. package/src/components/collapse/collapse.html +1 -1
  24. package/src/components/collapse/collapse.scss +2 -2
  25. package/src/components/collapse/collapse.vue +9 -9
  26. package/src/components/container/container.vue +2 -2
  27. package/src/components/decision-modal/decision-modal.scss +9 -9
  28. package/src/components/decision-modal/decision-modal.vue +8 -8
  29. package/src/components/divider/divider.scss +2 -2
  30. package/src/components/divider/divider.vue +4 -4
  31. package/src/components/dropdown/dropdown.scss +3 -3
  32. package/src/components/dropdown/dropdown.vue +7 -9
  33. package/src/components/field/field.type.ts +2 -2
  34. package/src/components/field/outline/outline.scss +15 -13
  35. package/src/components/field/outline/outline.vue +26 -18
  36. package/src/components/form-group/form-group.vue +2 -2
  37. package/src/components/gesture-indicator/gesture-indicator.scss +1 -1
  38. package/src/components/gesture-indicator/gesture-indicator.vue +4 -4
  39. package/src/components/image/image.vue +12 -5
  40. package/src/components/layout/flex/flex.vue +8 -8
  41. package/src/components/layout/flex-item/flex-item.vue +6 -6
  42. package/src/components/layout/grid/grid.vue +6 -6
  43. package/src/components/layout/grid-item/grid-item.vue +6 -6
  44. package/src/components/modal/modal.scss +1 -1
  45. package/src/components/modal/modal.vue +68 -5
  46. package/src/components/page/page.vue +2 -2
  47. package/src/components/present/present.scss +3 -3
  48. package/src/components/present/present.vue +14 -14
  49. package/src/components/radio/radio/radio.html +1 -1
  50. package/src/components/radio/radio/radio.scss +18 -13
  51. package/src/components/radio/radio/radio.type.ts +1 -1
  52. package/src/components/radio/radio/radio.vue +6 -6
  53. package/src/components/radio/radio-group/radio-group.vue +2 -2
  54. package/src/components/refresher/refresher.html +0 -3
  55. package/src/components/refresher/refresher.scss +1 -25
  56. package/src/components/refresher/refresher.vue +2 -16
  57. package/src/components/route/route-navigator/route-navigator.scss +2 -2
  58. package/src/components/route/route-navigator/route-navigator.vue +10 -13
  59. package/src/components/route/route-wrapper/route-wrapper.composable.ts +5 -15
  60. package/src/components/route/route-wrapper/route-wrapper.type.ts +0 -4
  61. package/src/components/route/route-wrapper/route-wrapper.vue +4 -12
  62. package/src/components/route/route.type.ts +0 -1
  63. package/src/components/segmented-field/segmented-field.html +1 -1
  64. package/src/components/segmented-field/segmented-field.scss +2 -2
  65. package/src/components/segmented-field/segmented-field.vue +8 -8
  66. package/src/components/select/select.html +2 -2
  67. package/src/components/select/select.scss +10 -10
  68. package/src/components/select/select.vue +10 -10
  69. package/src/components/skeleton/skeleton.vue +7 -7
  70. package/src/components/slide-range/slide-range.html +3 -4
  71. package/src/components/slide-range/slide-range.scss +10 -10
  72. package/src/components/slide-range/slide-range.vue +16 -16
  73. package/src/components/switch/switch.html +1 -1
  74. package/src/components/switch/switch.scss +22 -20
  75. package/src/components/switch/switch.type.ts +1 -0
  76. package/src/components/switch/switch.vue +23 -9
  77. package/src/components/tabs/tab/tab.html +1 -1
  78. package/src/components/tabs/tab/tab.scss +13 -0
  79. package/src/components/tabs/tab/tab.vue +4 -2
  80. package/src/components/tabs/tabs/index.ts +1 -0
  81. package/src/components/tabs/tabs/tabs.scss +81 -49
  82. package/src/components/tabs/tabs/tabs.type.ts +5 -1
  83. package/src/components/tabs/tabs/tabs.vue +47 -23
  84. package/src/components/toast/toast/toast.vue +2 -2
  85. package/src/components/toast/toast-content/toast-content.scss +3 -3
  86. package/src/components/toast/toast-content/toast-content.vue +5 -5
  87. package/src/components/toolbar/toolbar.scss +3 -3
  88. package/src/components/toolbar/toolbar.vue +5 -5
  89. package/src/factory.ts +105 -51
  90. package/src/type.ts +2 -1
  91. package/src/utils/style/index.ts +9 -9
  92. package/src/utils/style.md +9 -9
@@ -6,7 +6,7 @@ import { gesture as toifeGesture } from "@toife/gesture";
6
6
  import { Present } from "../present";
7
7
  import { GestureIndicator } from "../gesture-indicator";
8
8
  import { type ModalProps, type ModalEmit } from "./modal.type";
9
- import { withPrefix } from "../../utils";
9
+ import { cssPrefix } from "../../utils";
10
10
  import { type AppProviderState, APP_PROVIDER_STATE_KEY } from "../app";
11
11
 
12
12
  // Component setup (props, emits, injects)
@@ -47,10 +47,10 @@ const modalAttrs = computed(() => {
47
47
 
48
48
  return {
49
49
  class: [
50
- withPrefix(["layer", "modal"]),
51
- withPrefix(["role", role]),
52
- withPrefix(["shape", shape]),
53
- withPrefix("modal"),
50
+ cssPrefix(["layer", "modal"]),
51
+ cssPrefix(["role", role]),
52
+ cssPrefix(["shape", shape]),
53
+ cssPrefix("modal"),
54
54
  {
55
55
  fullscreen: props.fullscreen,
56
56
  [props.placement]: true,
@@ -67,6 +67,65 @@ const close = (e: string) => {
67
67
  emit("close", e);
68
68
  };
69
69
 
70
+ const SCROLLABLE_OVERFLOW_VALUES = ["auto", "scroll", "overlay"];
71
+
72
+ /**
73
+ * Check if the element is scrollable
74
+ * @param el - The element
75
+ * @param axis - The axis of the scroll
76
+ * @returns True if the element is scrollable, false otherwise
77
+ */
78
+ const isScrollable = (el: HTMLElement, axis: "x" | "y") => {
79
+ const style = getComputedStyle(el);
80
+ if (axis == "y") {
81
+ return (
82
+ el.scrollHeight > el.clientHeight && SCROLLABLE_OVERFLOW_VALUES.includes(style.overflowY)
83
+ );
84
+ }
85
+
86
+ return el.scrollWidth > el.clientWidth && SCROLLABLE_OVERFLOW_VALUES.includes(style.overflowX);
87
+ };
88
+
89
+ /**
90
+ * Check if the element has remaining scroll
91
+ * @param el - The element
92
+ * @param direction - The direction of the scroll
93
+ * @returns True if the element has remaining scroll, false otherwise
94
+ */
95
+ const hasRemainingScroll = (el: HTMLElement, direction: "up" | "down" | "left" | "right") => {
96
+ if (direction == "down") return el.scrollTop > 0;
97
+ if (direction == "up") return el.scrollTop < el.scrollHeight - el.clientHeight;
98
+ if (direction == "right") return el.scrollLeft > 0;
99
+
100
+ return el.scrollLeft < el.scrollWidth - el.clientWidth;
101
+ };
102
+
103
+ /**
104
+ * Check if the gesture can start
105
+ * @param e - The event
106
+ * @returns True if the gesture can start, false otherwise
107
+ */
108
+ const canStartGesture = (e: unknown) => {
109
+ if (!modal.value || !gestureDir.value) return true;
110
+
111
+ const target = (e as { target?: EventTarget }).target;
112
+ if (!(target instanceof Element)) return true;
113
+
114
+ const axis = gestureDir.value == "left" || gestureDir.value == "right" ? "x" : "y";
115
+ let current: Element | null = target;
116
+
117
+ while (current && current !== modal.value) {
118
+ if (current instanceof HTMLElement && isScrollable(current, axis)) {
119
+ if (hasRemainingScroll(current, gestureDir.value)) {
120
+ return false;
121
+ }
122
+ }
123
+ current = current.parentElement;
124
+ }
125
+
126
+ return true;
127
+ };
128
+
70
129
  // Cooldown so rapid gesture events do not fight the sheet animation
71
130
  const busy = () => {
72
131
  isBusy.value = true;
@@ -94,6 +153,10 @@ watch(
94
153
  return false;
95
154
  }
96
155
 
156
+ if (!canStartGesture(e)) {
157
+ return false;
158
+ }
159
+
97
160
  return true;
98
161
  },
99
162
 
@@ -1,10 +1,10 @@
1
1
  <template src="./page.html"></template>
2
2
  <style lang="scss" src="./page.scss" scoped></style>
3
3
  <script lang="ts" setup>
4
- import { withPrefix } from "../../utils";
4
+ import { cssPrefix } from "../../utils";
5
5
 
6
6
  // Top-level page surface inside the app shell
7
7
  const pageAttrs = {
8
- class: [withPrefix("page")],
8
+ class: [cssPrefix("page")],
9
9
  } as const;
10
10
  </script>
@@ -18,7 +18,7 @@ $present-translate-minus: sass.fn-naming-dvar(("translate"), "-100%");
18
18
  $present-opacity: sass.fn-naming-dvar(("present", "opacity"), 1);
19
19
 
20
20
  .#{$backdrop} {
21
- position: absolute;
21
+ position: fixed;
22
22
  width: 100%;
23
23
  height: 100%;
24
24
  top: 0;
@@ -30,7 +30,7 @@ $present-opacity: sass.fn-naming-dvar(("present", "opacity"), 1);
30
30
  color #{$transition-duration} ease,
31
31
  border-radius #{$transition-duration} ease,
32
32
  opacity #{$transition-duration} ease;
33
- background-color: rgb(#{$backdrop-background-color});
33
+ background-color: rgba(#{$backdrop-background-color});
34
34
  opacity: #{$backdrop-opacity};
35
35
  }
36
36
 
@@ -38,7 +38,7 @@ $present-opacity: sass.fn-naming-dvar(("present", "opacity"), 1);
38
38
  display: flex;
39
39
  justify-content: center;
40
40
  align-items: center;
41
- position: absolute;
41
+ position: fixed;
42
42
  width: fit-content;
43
43
  height: fit-content;
44
44
  transition: transform #{$transition-duration} ease;
@@ -3,7 +3,7 @@
3
3
  <script lang="ts" setup>
4
4
  import type { PresentEmit, PresentProps, RenderOptions } from "./present.type";
5
5
  import { computed, onMounted, reactive, ref, watch } from "vue";
6
- import { withPrefix, property } from "../../utils";
6
+ import { cssPrefix, cssProperty } from "../../utils";
7
7
  import { usePresent } from "./present.composable";
8
8
 
9
9
  // Component setup (props, emits, injects)
@@ -28,7 +28,7 @@ const zIndex = ref(0);
28
28
  const isShow = ref(false);
29
29
  const styles = reactive({
30
30
  backdropTransitionDuration: "0.2s",
31
- backdropOpacity: 0.4,
31
+ backdropOpacity: undefined,
32
32
  presentTransitionDuration: "0.2s",
33
33
  presentTranslate: "0px",
34
34
  presentOpacity: 1,
@@ -38,11 +38,11 @@ const styles = reactive({
38
38
  // ----------------------------------------------------------------------------
39
39
  const backdropAttrs = computed(() => {
40
40
  return {
41
- class: [withPrefix(["layer", "backdrop"]), withPrefix("present-backdrop")],
41
+ class: [cssPrefix(["layer", "backdrop"]), cssPrefix("present-backdrop")],
42
42
  style: {
43
43
  zIndex: zIndex.value - 1,
44
- [property("transition-duration")]: styles.backdropTransitionDuration,
45
- [property(["backdrop", "opacity"])]:
44
+ [cssProperty("transition-duration")]: styles.backdropTransitionDuration,
45
+ [cssProperty(["backdrop", "opacity"])]:
46
46
  props.backdrop === "transparent" ? 0 : styles.backdropOpacity,
47
47
  },
48
48
  };
@@ -51,13 +51,13 @@ const backdropAttrs = computed(() => {
51
51
  // Present attributes
52
52
  const presentAttrs = computed(() => {
53
53
  return {
54
- class: [withPrefix("present"), props.class, props.placement],
54
+ class: [cssPrefix("present"), props.class, props.placement],
55
55
  style: [
56
56
  {
57
57
  zIndex: zIndex.value,
58
- [property("transition-duration")]: styles.presentTransitionDuration,
59
- [property("translate")]: styles.presentTranslate,
60
- [property(["present", "opacity"])]: styles.presentOpacity,
58
+ [cssProperty("transition-duration")]: styles.presentTransitionDuration,
59
+ [cssProperty("translate")]: styles.presentTranslate,
60
+ [cssProperty(["present", "opacity"])]: styles.presentOpacity,
61
61
  },
62
62
  props.style,
63
63
  ],
@@ -87,9 +87,9 @@ const render = (data: RenderOptions) => {
87
87
  if (data.presentTransitionDuration !== undefined) {
88
88
  styles.presentTransitionDuration = data.presentTransitionDuration;
89
89
  }
90
- if (data.backdropOpacity !== undefined) {
91
- styles.backdropOpacity = data.backdropOpacity;
92
- }
90
+
91
+ styles.backdropOpacity = data.backdropOpacity;
92
+
93
93
  if (data.presentTranslate !== undefined) {
94
94
  styles.presentTranslate = data.presentTranslate;
95
95
  }
@@ -115,7 +115,7 @@ const open = () => {
115
115
 
116
116
  render({
117
117
  backdropTransitionDuration: time.value,
118
- backdropOpacity: 0.4,
118
+ backdropOpacity: undefined,
119
119
  presentTranslate: String(presentTranslate),
120
120
  presentTransitionDuration: time.value,
121
121
  presentOpacity: 1,
@@ -128,7 +128,7 @@ const open = () => {
128
128
  }, props.duration);
129
129
  } else {
130
130
  render({
131
- backdropOpacity: 0.4,
131
+ backdropOpacity: undefined,
132
132
  backdropTransitionDuration: time.value,
133
133
  presentTranslate: "0px",
134
134
  presentTransitionDuration: time.value,
@@ -1,6 +1,6 @@
1
1
  <div
2
2
  v-bind="radioAttrs"
3
- @click="onRadio"
3
+ @pointerup="onRadio"
4
4
  :tabindex="disabled ? -1 : 0"
5
5
  @focus="onFocus"
6
6
  @blur="onBlur"
@@ -11,7 +11,11 @@ $radio-background-color-unchecked: sass.fn-naming-var("radio", "background-color
11
11
  $radio-background-color-checked: sass.fn-naming-var("radio", "background-color", "checked");
12
12
  $radio-background-color-disabled: sass.fn-naming-var("radio", "background-color", "disabled");
13
13
 
14
- $radio-color: sass.fn-naming-var("radio", "color");
14
+ $radio-color-unchecked: sass.fn-naming-var("radio", "color", "unchecked");
15
+ $radio-color-checked: sass.fn-naming-var("radio", "color", "checked");
16
+ $radio-color-hover: sass.fn-naming-var("radio", "color", "hover");
17
+ $radio-color-focus: sass.fn-naming-var("radio", "color", "focus");
18
+ $radio-color-disabled: sass.fn-naming-var("radio", "color", "disabled");
15
19
 
16
20
  $radio-border-color-hover: sass.fn-naming-var("radio", "border-color", "hover");
17
21
  $radio-border-color-focus: sass.fn-naming-var("radio", "border-color", "focus");
@@ -42,8 +46,8 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
42
46
  display: flex;
43
47
  align-items: center;
44
48
  justify-content: center;
45
- border: 1px solid rgb(#{$radio-color});
46
49
  background-color: transparent;
50
+ border: 1px solid transparent;
47
51
  transition:
48
52
  box-shadow #{$transition-duration} ease,
49
53
  border-color #{$transition-duration} ease,
@@ -59,7 +63,7 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
59
63
  width: calc(#{$size-control-mark-size} * 0.5);
60
64
  height: calc(#{$size-control-mark-size} * 0.5);
61
65
  border-radius: 50%;
62
- background-color: rgb(#{$radio-color});
66
+ background-color: rgba(#{$radio-color-unchecked});
63
67
  transform: scale(0);
64
68
  transform-origin: center;
65
69
  transition:
@@ -73,12 +77,12 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
73
77
  &:not(.on) {
74
78
  .#{$radio-icon} {
75
79
  background-color: transparent;
76
- border-color: rgb(#{$radio-border-color-unchecked});
80
+ border-color: rgba(#{$radio-border-color-unchecked});
77
81
  }
78
82
 
79
83
  &:not(.disabled):not(.readonly):hover {
80
84
  .#{$radio-icon} {
81
- border-color: rgb(#{$radio-border-color-hover});
85
+ border-color: rgba(#{$radio-border-color-hover});
82
86
  }
83
87
  }
84
88
  }
@@ -86,22 +90,23 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
86
90
  &.on {
87
91
  &.fill {
88
92
  .#{$radio-icon} {
89
- background-color: rgb(#{$radio-background-color-checked});
90
- border-color: rgb(#{$radio-border-color-checked});
93
+ background-color: rgba(#{$radio-background-color-checked});
94
+ border-color: rgba(#{$radio-border-color-checked});
91
95
 
92
96
  &::after {
93
97
  transform: scale(1);
98
+ background-color: rgba(#{$radio-color-checked});
94
99
  }
95
100
  }
96
101
  }
97
102
 
98
103
  &.outline {
99
104
  .#{$radio-icon} {
100
- border-color: rgb(#{$radio-border-color-checked});
105
+ border-color: rgba(#{$radio-border-color-checked});
101
106
 
102
107
  &::after {
103
108
  transform: scale(1);
104
- background-color: rgb(#{$radio-background-color-checked});
109
+ background-color: rgba(#{$radio-background-color-checked});
105
110
  }
106
111
  }
107
112
  }
@@ -113,8 +118,8 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
113
118
 
114
119
  &.on {
115
120
  .#{$radio-icon} {
116
- background-color: rgb(#{$radio-background-color-disabled});
117
- border-color: rgb(#{$radio-border-color-disabled});
121
+ background-color: rgba(#{$radio-background-color-disabled});
122
+ border-color: rgba(#{$radio-border-color-disabled});
118
123
  }
119
124
  }
120
125
  }
@@ -126,12 +131,12 @@ $size-control-mark-size: sass.fn-naming-var("control-mark-size");
126
131
  &.focus {
127
132
  &.shadow {
128
133
  .#{$radio-icon} {
129
- box-shadow: 0 0 0 0.25rem rgb(#{$radio-box-shadow-color-focus}, 0.25);
134
+ box-shadow: 0 0 0 0.25rem rgba(#{$radio-box-shadow-color-focus}, 0.25);
130
135
  }
131
136
  }
132
137
 
133
138
  .#{$radio-icon} {
134
- border-color: rgb(#{$radio-border-color-focus});
139
+ border-color: rgba(#{$radio-border-color-focus});
135
140
  }
136
141
  }
137
142
  }
@@ -1,4 +1,4 @@
1
- import { AppSize } from "@/components/app";
1
+ import { AppSize } from "../../app";
2
2
 
3
3
  export type RadioVariant = "fill" | "outline";
4
4
  export type RadioSize = AppSize;
@@ -3,7 +3,7 @@
3
3
  <script lang="ts" setup>
4
4
  import { computed, inject, ref } from "vue";
5
5
  import type { RadioProps } from "./radio.type";
6
- import { withPrefix } from "../../../utils";
6
+ import { cssPrefix } from "../../../utils";
7
7
  import { type AppProviderState, APP_PROVIDER_STATE_KEY } from "../../app";
8
8
  import { type RadioGroupProviderState, RADIO_GROUP_PROVIDER_STATE_KEY } from "../radio-group";
9
9
 
@@ -42,10 +42,10 @@ const radioAttrs = computed(() => {
42
42
 
43
43
  return {
44
44
  class: [
45
- withPrefix(["layer", "radio"]),
46
- withPrefix(["role", role]),
47
- withPrefix(["size", props.size]),
48
- withPrefix("radio"),
45
+ cssPrefix(["layer", "radio"]),
46
+ cssPrefix(["role", role]),
47
+ cssPrefix(["size", props.size]),
48
+ cssPrefix("radio"),
49
49
  variant,
50
50
  {
51
51
  on: isChecked,
@@ -59,7 +59,7 @@ const radioAttrs = computed(() => {
59
59
  });
60
60
 
61
61
  const radioIconAttrs = {
62
- class: [withPrefix("radio-icon")],
62
+ class: [cssPrefix("radio-icon")],
63
63
  } as const;
64
64
 
65
65
  // Methods
@@ -3,7 +3,7 @@
3
3
  <script lang="ts" setup>
4
4
  import { computed, inject, provide } from "vue";
5
5
  import type { RadioGroupProps, RadioGroupEmit, RadioGroupProviderState } from "./radio-group.type";
6
- import { withPrefix } from "../../../utils";
6
+ import { cssPrefix } from "../../../utils";
7
7
  import { type AppProviderState, APP_PROVIDER_STATE_KEY } from "../../app";
8
8
  import { RADIO_GROUP_PROVIDER_STATE_KEY } from "./radio-group.constants";
9
9
 
@@ -37,7 +37,7 @@ const shadow = computed(() => {
37
37
 
38
38
  const radioGroupAttrs = computed(() => {
39
39
  return {
40
- class: [withPrefix("radio-group"), props.direction],
40
+ class: [cssPrefix("radio-group"), props.direction],
41
41
  };
42
42
  });
43
43
 
@@ -1,6 +1,3 @@
1
1
  <div v-bind="containerAttrs" ref="container">
2
- <div v-bind="refresherIconAttrs" v-show="calculateOffset > 0">
3
- <slot name="icon" :offset="calculateOffset" :refreshing="refreshing"></slot>
4
- </div>
5
2
  <slot :offset="calculateOffset" :refreshing="refreshing"></slot>
6
3
  </div>
@@ -1,14 +1,8 @@
1
1
  @use "@toife/sass-layer" as sass;
2
2
 
3
3
  // Class
4
- $refresher-icon: sass.fn-naming-prefix("refresher-icon");
5
4
  $container: sass.fn-naming-prefix("refresher");
6
5
 
7
- // Variables
8
- $safe-area-top: sass.fn-naming-var("safe-area", "top");
9
- $transition-duration: sass.fn-naming-var("motion", "duration");
10
- $offset: sass.fn-naming-var("refresher-offset");
11
-
12
6
  .#{$container} {
13
7
  width: 100%;
14
8
  height: 100%;
@@ -20,23 +14,5 @@ $offset: sass.fn-naming-var("refresher-offset");
20
14
  right: 0;
21
15
  bottom: 0;
22
16
  overflow: auto;
23
- }
24
-
25
- // Refresher
26
- .#{$refresher-icon} {
27
- display: flex;
28
- justify-content: center;
29
- align-items: center;
30
- overflow: hidden;
31
- transition: height #{$transition-duration} ease;
32
- position: absolute;
33
- top: 0;
34
- left: 50%;
35
- transform: translateX(-50%);
36
- line-height: 0;
37
- z-index: 1;
38
-
39
- &.moving {
40
- top: calc(#{$safe-area-top} + #{$offset});
41
- }
17
+ overscroll-behavior: none;
42
18
  }
@@ -4,7 +4,7 @@
4
4
  import { ref, onUnmounted, watch, computed } from "vue";
5
5
  import { gesture } from "@toife/gesture";
6
6
  import type { RefresherProps, RefresherEmit } from "./refresher.type";
7
- import { property, withPrefix } from "../../utils";
7
+ import { cssProperty, cssPrefix } from "../../utils";
8
8
 
9
9
  // Component setup (props, emits, injects)
10
10
  // ----------------------------------------------------------------------------
@@ -29,23 +29,9 @@ const calculateOffset = computed(() => {
29
29
  return props.offset !== undefined ? props.offset : moveOffset.value / 2;
30
30
  });
31
31
 
32
- const refresherIconAttrs = computed(() => {
33
- return {
34
- style: {
35
- [property("refresher-offset")]: `${calculateOffset.value}px`,
36
- },
37
- class: [
38
- withPrefix("refresher-icon"),
39
- {
40
- moving: calculateOffset.value > 0,
41
- },
42
- ],
43
- };
44
- });
45
-
46
32
  const containerAttrs = computed(() => {
47
33
  return {
48
- class: [withPrefix("refresher")],
34
+ class: [cssPrefix("refresher")],
49
35
  };
50
36
  });
51
37
 
@@ -50,7 +50,7 @@ $backdrop-background-color: sass.fn-naming-var("backdrop", "background-color");
50
50
  height: 100%;
51
51
  top: 0;
52
52
  left: 0;
53
- background-color: rgb(#{$backdrop-background-color});
53
+ background-color: rgba(#{$backdrop-background-color});
54
54
  opacity: calc(#{$backdrop-opacity} * (#{$backdrop-percent} / 100));
55
55
  transition: opacity #{$transition-duration} ease;
56
56
  }
@@ -64,7 +64,7 @@ $backdrop-background-color: sass.fn-naming-var("backdrop", "background-color");
64
64
  top: 0;
65
65
  left: 0;
66
66
  flex: none;
67
- background-color: rgb(#{$background-color});
67
+ background-color: rgba(#{$background-color});
68
68
  transform: translate(0, 0);
69
69
  transition:
70
70
  transform #{$transition-duration} ease,
@@ -3,7 +3,7 @@
3
3
  <script lang="ts" setup>
4
4
  import { computed, inject, onMounted, onUnmounted, reactive, ref, watch } from "vue";
5
5
  import { gesture } from "@toife/gesture";
6
- import { withPrefix, property } from "../../../utils";
6
+ import { cssPrefix, cssProperty } from "../../../utils";
7
7
  import type {
8
8
  RouteNavigatorEmit,
9
9
  RouteNavigatorProps,
@@ -63,26 +63,26 @@ const navigatorAttrs = computed(() => {
63
63
  }
64
64
 
65
65
  return {
66
- class: [withPrefix("route-navigator"), props.direction, props.variant],
66
+ class: [cssPrefix("route-navigator"), props.direction, props.variant],
67
67
  style: {
68
- [property("route-navigator-transform-back")]: transform.back + "%",
69
- [property("route-navigator-transform-prepare")]: transform.prepare + "%",
70
- [property("route-navigator-transform-active")]: transform.active + "%",
71
- [property("route-navigator-transition-duration")]: duration,
72
- [property("route-navigator-backdrop-percent")]: transform.backdrop,
68
+ [cssProperty("route-navigator-transform-back")]: transform.back + "%",
69
+ [cssProperty("route-navigator-transform-prepare")]: transform.prepare + "%",
70
+ [cssProperty("route-navigator-transform-active")]: transform.active + "%",
71
+ [cssProperty("route-navigator-transition-duration")]: duration,
72
+ [cssProperty("route-navigator-backdrop-percent")]: transform.backdrop,
73
73
  },
74
74
  };
75
75
  });
76
76
 
77
77
  const componentAttrs = computed(() => {
78
78
  return {
79
- class: [withPrefix("route-navigator-component"), props.direction],
79
+ class: [cssPrefix("route-navigator-component"), props.direction],
80
80
  };
81
81
  });
82
82
 
83
83
  const backdropAttrs = computed(() => {
84
84
  return {
85
- class: [withPrefix("route-navigator-backdrop"), withPrefix(["layer", "backdrop"])],
85
+ class: [cssPrefix("route-navigator-backdrop"), cssPrefix(["layer", "backdrop"])],
86
86
  style: {
87
87
  zIndex: backdropIndex.value * 2 - 1,
88
88
  },
@@ -158,7 +158,7 @@ const goBack = () => {
158
158
  if (activeIndex.value <= 0) return;
159
159
  const prev = stack.value[activeIndex.value - 1];
160
160
  if (!prev) return;
161
- router.push(prev.fullPath);
161
+ router.back();
162
162
  };
163
163
 
164
164
  const resetTransform = () => {
@@ -230,7 +230,6 @@ onMounted(() => {
230
230
 
231
231
  fast({ initialDirection, event }: { initialDirection: string; event: Event }) {
232
232
  if (initialDirection !== props.direction) return;
233
- event.preventDefault();
234
233
  goBack();
235
234
  },
236
235
 
@@ -246,7 +245,6 @@ onMounted(() => {
246
245
  event: Event;
247
246
  }) {
248
247
  if (initialDirection !== props.direction) return;
249
- event.preventDefault();
250
248
  move({ deltaX, deltaY });
251
249
  },
252
250
 
@@ -262,7 +260,6 @@ onMounted(() => {
262
260
  event: Event;
263
261
  }) {
264
262
  if (initialDirection !== props.direction) return;
265
- event.preventDefault();
266
263
  up({ deltaX, deltaY });
267
264
  },
268
265
 
@@ -1,16 +1,11 @@
1
1
  import { shallowRef } from "vue";
2
2
  import { type RouteComponent, type RouteLocationMatched } from "vue-router";
3
3
  import { type RouteStack } from "../route.type";
4
- import { RouteWrapperOption } from "./route-wrapper.type";
5
4
 
6
5
  const stack = shallowRef<RouteStack[]>([]);
7
6
 
8
7
  /** Recursively builds a nested stack from vue-router `matched` for the navigator. */
9
- const buildTree = (
10
- matched: RouteLocationMatched[],
11
- current: RouteStack[],
12
- option: RouteWrapperOption
13
- ) => {
8
+ const buildTree = (matched: RouteLocationMatched[], current: RouteStack[]) => {
14
9
  if (matched.length === 0) return current;
15
10
 
16
11
  // User navigated back: drop the leaf so we merge into the parent segment
@@ -25,11 +20,7 @@ const buildTree = (
25
20
  current[current.length - 1].name === matched[0].name
26
21
  ) {
27
22
  matched.shift();
28
- current[current.length - 1].stack = buildTree(
29
- matched,
30
- current[current.length - 1].stack,
31
- option
32
- );
23
+ current[current.length - 1].stack = buildTree(matched, current[current.length - 1].stack);
33
24
  }
34
25
  // Push a new segment (forward navigation)
35
26
  else {
@@ -39,8 +30,7 @@ const buildTree = (
39
30
  current.push({
40
31
  name,
41
32
  component,
42
- fullPath: option.fullPath,
43
- stack: buildTree(matched, [], option),
33
+ stack: buildTree(matched, []),
44
34
  });
45
35
  }
46
36
 
@@ -48,8 +38,8 @@ const buildTree = (
48
38
  };
49
39
 
50
40
  export const useRouteWrapper = () => {
51
- const updateRoutes = (matched: RouteLocationMatched[], option: RouteWrapperOption) => {
52
- stack.value = buildTree([...matched], [...stack.value], option);
41
+ const updateRoutes = (matched: RouteLocationMatched[]) => {
42
+ stack.value = buildTree([...matched], [...stack.value]);
53
43
  };
54
44
 
55
45
  return {
@@ -1,7 +1,3 @@
1
1
  export type RouteWrapperProps = {
2
2
  homeRouteName?: string;
3
3
  };
4
-
5
- export type RouteWrapperOption = {
6
- fullPath: string;
7
- };
@@ -20,9 +20,7 @@ const router = useRouter();
20
20
  watch(
21
21
  () => route.matched,
22
22
  () => {
23
- updateRoutes(route.matched, {
24
- fullPath: route.fullPath,
25
- });
23
+ updateRoutes(route.matched);
26
24
  }
27
25
  );
28
26
 
@@ -31,22 +29,16 @@ onMounted(() => {
31
29
  const homeName = props.homeRouteName;
32
30
 
33
31
  if (route.name === homeName) {
34
- updateRoutes(route.matched, {
35
- fullPath: route.fullPath,
36
- });
32
+ updateRoutes(route.matched);
37
33
  } else {
38
34
  const homeLocation = router.resolve({ name: homeName });
39
35
  if (homeLocation.matched.length > 0) {
40
- updateRoutes(homeLocation.matched, {
41
- fullPath: homeLocation.fullPath,
42
- });
36
+ updateRoutes(homeLocation.matched);
43
37
  }
44
38
 
45
39
  // Apply current route to stack
46
40
  setTimeout(() => {
47
- updateRoutes(route.matched, {
48
- fullPath: route.fullPath,
49
- });
41
+ updateRoutes(route.matched);
50
42
  }, 50);
51
43
  }
52
44
  });
@@ -3,6 +3,5 @@ import { RouteComponent } from "vue-router";
3
3
  export type RouteStack = {
4
4
  name: string;
5
5
  component: RouteComponent;
6
- fullPath: string;
7
6
  stack: RouteStack[];
8
7
  };