@apptegy/nuxt-navigation 0.1.79 → 0.1.80

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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=3.0.0"
5
5
  },
6
6
  "configKey": "@apptegy/nuxt-navigation",
7
- "version": "0.1.79",
7
+ "version": "0.1.80",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.1",
10
10
  "unbuild": "unknown"
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useDropdown, useNuxtApp, useAppConfig, computed, ref } from "#imports";
2
+ import { useDropdown, useNuxtApp, useAppConfig, computed, ref, watch } from "#imports";
3
3
  import { vOnClickOutside } from "@vueuse/components";
4
4
  const { $t } = useNuxtApp();
5
5
  const appConfig = useAppConfig();
@@ -8,13 +8,17 @@ const emit = defineEmits(["update:model-value"]);
8
8
  const dropdownTriggerRef = ref();
9
9
  const inputRef = ref();
10
10
  const optionRef = ref();
11
- const selectedOrg = computed(() => {
12
- return props.orgs.find(({ id }) => id == props.modelValue);
13
- });
14
11
  const props = defineProps({
15
12
  orgs: { type: Array, required: true },
16
13
  modelValue: { type: Number, required: true }
17
14
  });
15
+ const localSelectedOrgId = ref(props.modelValue);
16
+ watch(() => props.modelValue, (newValue) => {
17
+ localSelectedOrgId.value = newValue;
18
+ });
19
+ const selectedOrg = computed(() => {
20
+ return props.orgs.find(({ id }) => id == localSelectedOrgId.value);
21
+ });
18
22
  const {
19
23
  active,
20
24
  searchQuery,
@@ -48,11 +52,16 @@ const highlightedOrg = computed(() => {
48
52
  });
49
53
  function handleSelectedOrg($event, orgId) {
50
54
  if ($event.type == "click") {
55
+ localSelectedOrgId.value = orgId;
51
56
  emit("update:model-value", orgId);
52
57
  closeDropdown();
53
58
  } else if ($event.type == "keydown") {
54
- emit("update:model-value", orgId);
55
- handleKeydown($event, orgId);
59
+ const keyEvent = $event;
60
+ if (keyEvent.key === "Enter" || keyEvent.key === " ") {
61
+ localSelectedOrgId.value = orgId;
62
+ emit("update:model-value", orgId);
63
+ }
64
+ handleKeydown(keyEvent, orgId);
56
65
  }
57
66
  }
58
67
  </script>
@@ -106,10 +115,10 @@ function handleSelectedOrg($event, orgId) {
106
115
  role="option"
107
116
  class="org-option"
108
117
  :class="{
109
- selected: option.id === modelValue,
118
+ selected: option.id === localSelectedOrgId,
110
119
  highlighted: highlightedOrg && option.id === highlightedOrg.id
111
120
  }"
112
- :aria-selected="option.id === modelValue"
121
+ :aria-selected="option.id === localSelectedOrgId"
113
122
  tabindex="-1"
114
123
  @keydown="handleSelectedOrg($event, option.id)"
115
124
  @click="handleSelectedOrg($event, option.id)"
@@ -7,6 +7,8 @@
7
7
  :style="getBrandingStyles"
8
8
  @mouseenter="!lockedExpanded && onHover()"
9
9
  @mouseleave="!lockedExpanded && onHoverLeave()"
10
+ @focusin="!lockedExpanded && onFocusEnter()"
11
+ @focusout="!lockedExpanded && onFocusLeave()"
10
12
  >
11
13
  <a
12
14
  :href="`#${skipToContent}`"
@@ -42,7 +44,7 @@
42
44
  <button v-if="!lockedExpanded && allowCollapse && expanded" class="hamburger-button" @click="lockSidebar" v-tooltip.bottom="'Pin menu open'">
43
45
  <Unpinned />
44
46
  </button>
45
- <button v-if="!lockedExpanded && allowCollapse && !expanded" class="hamburger-button" @click="onHover">
47
+ <button v-if="!lockedExpanded && allowCollapse && !expanded" class="hamburger-button">
46
48
  <a-icon icon="24:hamburger" />
47
49
  </button>
48
50
  </div>
@@ -136,6 +138,7 @@ const breakpoints = useBreakpoints(breakpointsTailwind);
136
138
  const isMobile = breakpoints.smaller("md");
137
139
  const lockedExpanded = ref(true);
138
140
  const allowCollapse = ref(false);
141
+ let focusOutTimeout = null;
139
142
  function updateBrandLogoWidth() {
140
143
  brandLogoWidthPx.value = brandLogoRef.value?.clientWidth ?? 0;
141
144
  }
@@ -151,6 +154,10 @@ onMounted(() => {
151
154
  onBeforeUnmount(() => {
152
155
  brandLogoResizeObserver?.disconnect();
153
156
  brandLogoResizeObserver = null;
157
+ if (focusOutTimeout) {
158
+ clearTimeout(focusOutTimeout);
159
+ focusOutTimeout = null;
160
+ }
154
161
  });
155
162
  watch(expanded, (value) => {
156
163
  emit("toggle-expand", value ? 264 : 64);
@@ -172,6 +179,23 @@ function onHoverLeave() {
172
179
  expanded.value = false;
173
180
  }
174
181
  }
182
+ function onFocusEnter() {
183
+ if (focusOutTimeout) {
184
+ clearTimeout(focusOutTimeout);
185
+ focusOutTimeout = null;
186
+ }
187
+ if (!expanded.value) {
188
+ expanded.value = true;
189
+ }
190
+ }
191
+ function onFocusLeave() {
192
+ focusOutTimeout = setTimeout(() => {
193
+ if (expanded.value) {
194
+ expanded.value = false;
195
+ }
196
+ focusOutTimeout = null;
197
+ }, 100);
198
+ }
175
199
  function closeSidebar() {
176
200
  expanded.value = false;
177
201
  lockedExpanded.value = false;
@@ -104,7 +104,7 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
104
104
  case "End":
105
105
  openDropdown();
106
106
  nextTick(() => {
107
- dropdownOptionsRef.value[options.length - 1].focus();
107
+ dropdownOptionsRef.value[options.length - 1]?.focus();
108
108
  });
109
109
  break;
110
110
  default:
@@ -148,13 +148,13 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
148
148
  case "ArrowDown":
149
149
  if (index === options.length - 1) break;
150
150
  nextTick(() => {
151
- dropdownOptionsRef.value[index + 1].focus();
151
+ dropdownOptionsRef.value[index + 1]?.focus();
152
152
  });
153
153
  return index;
154
154
  case "ArrowUp":
155
155
  if (index === 0) break;
156
156
  nextTick(() => {
157
- dropdownOptionsRef.value[index - 1].focus();
157
+ dropdownOptionsRef.value[index - 1]?.focus();
158
158
  });
159
159
  return index;
160
160
  case "ArrowLeft":
@@ -162,22 +162,22 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
162
162
  break;
163
163
  case "Home":
164
164
  nextTick(() => {
165
- dropdownOptionsRef.value[0].focus();
165
+ dropdownOptionsRef.value[0]?.focus();
166
166
  });
167
167
  return index;
168
168
  case "End":
169
169
  nextTick(() => {
170
- dropdownOptionsRef.value[options.length - 1].focus();
170
+ dropdownOptionsRef.value[options.length - 1]?.focus();
171
171
  });
172
172
  return index;
173
173
  case "PageDown": {
174
174
  const pageDownIndexToJump = index + 10 > options.length ? index + 10 : options.length - 1;
175
- dropdownOptionsRef.value[pageDownIndexToJump].focus();
175
+ dropdownOptionsRef.value[pageDownIndexToJump]?.focus();
176
176
  return index;
177
177
  }
178
178
  case "PageUp": {
179
179
  const pageUpIndexToJump = index - 10 < 0 ? index - 10 : 0;
180
- dropdownOptionsRef.value[pageUpIndexToJump].focus();
180
+ dropdownOptionsRef.value[pageUpIndexToJump]?.focus();
181
181
  return index;
182
182
  }
183
183
  default:
@@ -186,7 +186,7 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
186
186
  }
187
187
  }
188
188
  const debouncedFocus = useDebounceFn((idx) => {
189
- dropdownOptionsRef.value[idx].focus();
189
+ dropdownOptionsRef.value[idx]?.focus();
190
190
  }, 500);
191
191
  function handleDropdownSearch(inputValue) {
192
192
  if (!config.searchable) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apptegy/nuxt-navigation",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -27,24 +27,24 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@apptegy/nuxt-intl": "^2.4.2",
30
- "@nuxt/kit": "^3.17.0",
31
- "@vueuse/components": "^12.0.0",
32
- "@vueuse/core": "^12.0.0"
30
+ "@nuxt/kit": "catalog:",
31
+ "@vueuse/components": "catalog:shared",
32
+ "@vueuse/core": "catalog:shared"
33
33
  },
34
34
  "devDependencies": {
35
- "@nuxt/devtools": "^2.6.2",
36
- "@nuxt/eslint-config": "^1.6.0",
37
- "@nuxt/module-builder": "^1.0.1",
38
- "@nuxt/schema": "^3.17.0",
39
- "@nuxt/test-utils": "^3.17.0",
40
- "@types/node": "^22.0.0",
41
- "eslint": "^9.31.0",
42
- "nuxt": "^3.17.0",
43
- "sass": "^1.89.2",
44
- "typescript": "~5.8.0",
45
- "vitest": "^3.2.4",
46
- "vue": "^3.5.13",
47
- "vue-tsc": "^3.0.3"
35
+ "@nuxt/devtools": "catalog:",
36
+ "@nuxt/eslint-config": "catalog:",
37
+ "@nuxt/module-builder": "catalog:",
38
+ "@nuxt/schema": "catalog:",
39
+ "@nuxt/test-utils": "catalog:",
40
+ "@types/node": "catalog:",
41
+ "eslint": "catalog:",
42
+ "nuxt": "catalog:",
43
+ "sass": "catalog:",
44
+ "typescript": "catalog:",
45
+ "vitest": "catalog:",
46
+ "vue": "catalog:",
47
+ "vue-tsc": "catalog:"
48
48
  },
49
- "gitHead": "edcb211c421e908188dc18cda3ce4be1adb7cf97"
49
+ "gitHead": "f14058171ae6d317cea14c5267383913234c4117"
50
50
  }