@apptegy/nuxt-navigation 0.1.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.
Files changed (37) hide show
  1. package/README.md +84 -0
  2. package/dist/module.cjs +5 -0
  3. package/dist/module.d.mts +7 -0
  4. package/dist/module.d.ts +7 -0
  5. package/dist/module.json +9 -0
  6. package/dist/module.mjs +22 -0
  7. package/dist/runtime/assets/edurooms-logo-white.svg +1 -0
  8. package/dist/runtime/assets/edurooms-logo.svg +1 -0
  9. package/dist/runtime/assets/icons/24/Minus.svg +5 -0
  10. package/dist/runtime/assets/icons/24/Plus.svg +5 -0
  11. package/dist/runtime/assets/icons/32/logout.svg +4 -0
  12. package/dist/runtime/assets/img/help-toggle.svg +13 -0
  13. package/dist/runtime/assets/img/help.svg +5 -0
  14. package/dist/runtime/assets/img/impersonate-user.svg +3 -0
  15. package/dist/runtime/assets/img/navbar-minus.svg +3 -0
  16. package/dist/runtime/assets/img/navbar-plus.svg +3 -0
  17. package/dist/runtime/assets/img/navbar-up.svg +3 -0
  18. package/dist/runtime/assets/img/user.svg +8 -0
  19. package/dist/runtime/assets/logo.svg +56 -0
  20. package/dist/runtime/assets/thrillshare-icon-white.svg +1 -0
  21. package/dist/runtime/assets/thrillshare-logo-white.svg +1 -0
  22. package/dist/runtime/components/Nav/Avatar.vue +61 -0
  23. package/dist/runtime/components/Nav/Breadcrumb.vue +23 -0
  24. package/dist/runtime/components/Nav/Header.vue +200 -0
  25. package/dist/runtime/components/Nav/HelpArticles.vue +154 -0
  26. package/dist/runtime/components/Nav/ImpersonateInfoPanel.vue +135 -0
  27. package/dist/runtime/components/Nav/OrgSelect.vue +198 -0
  28. package/dist/runtime/components/Nav/Sidebar.vue +187 -0
  29. package/dist/runtime/components/Nav/SidebarItem.vue +40 -0
  30. package/dist/runtime/components/Nav/SidebarSection.vue +73 -0
  31. package/dist/runtime/components/Nav/SubMenu.vue +37 -0
  32. package/dist/runtime/components/Nav/SubMenuItem.vue +66 -0
  33. package/dist/runtime/composables/accessibleActions.d.ts +33 -0
  34. package/dist/runtime/composables/accessibleActions.js +195 -0
  35. package/dist/types.d.mts +1 -0
  36. package/dist/types.d.ts +1 -0
  37. package/package.json +49 -0
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div class="a-nav-section" :class="{ active }">
3
+ <NuxtLink class="a-nav-section--link" :to="application.url">
4
+ <img v-if="application.img_src" :src="iconUrl" alt="icon">
5
+ <span>{{ application.text.replace("_", " ") }}</span>
6
+ <a-icon v-if="active" class="caret-icon" icon="16:carret-up" />
7
+ </NuxtLink>
8
+ <div class="a-nav-section--content">
9
+ <slot />
10
+ </div>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { computed } from 'vue';
16
+
17
+ const props = defineProps<{
18
+ application: IApplication;
19
+ active: boolean;
20
+ navbarExpanded: boolean;
21
+ }>();
22
+
23
+ const iconUrl = computed(() =>
24
+ props.active
25
+ ? props.application.img_src?.replace(".svg", "_active.svg")
26
+ : props.application.img_src,
27
+ );
28
+ </script>
29
+
30
+ <style scoped>
31
+ .a-nav-section {
32
+ box-shadow: inset 0px -1px 0px 0px var(--dscl-nav-section-border-bottom-color, var(--purple-65));
33
+ cursor: pointer;
34
+ min-height: 48px;
35
+ /* &--content {
36
+ margin-bottom: 8px;
37
+ } */
38
+ }
39
+ .a-nav-section.active {
40
+ box-shadow: inset 0px -1px 0px 0px var(--dscl-nav-section-border-bottom-color, var(--purple-65));
41
+ padding-bottom: 4px;
42
+ }
43
+ .a-nav-section--link {
44
+ display: flex;
45
+ color: var(--dscl-nav-font-color, var(--dscl-light-font, var(--primary-white)));
46
+ text-decoration: none;
47
+ min-height: 48px;
48
+ align-items: center;
49
+ font-size: 12px;
50
+ letter-spacing: 1.4px;
51
+ overflow: hidden;
52
+ padding: 0px 16px;
53
+ width: 100%;
54
+ }
55
+ .a-nav-section--link:focus-visible {
56
+ outline: var(--orange) auto 2px;
57
+ outline-offset: 0px;
58
+ box-shadow: inset 0 0 0px 4px var(--primary-white);
59
+ }
60
+ .a-nav-section--link span {
61
+ margin: 0 8px;
62
+ white-space: nowrap;
63
+ text-transform: uppercase;
64
+ width: inherit;
65
+ }
66
+ .a-nav-section--link .caret-icon {
67
+ font-size: 24px;
68
+ transition: transform 0.2s ease-in-out;
69
+ }
70
+ .a-nav-section--link .caret-icon.collapse {
71
+ transform: rotate(0.5turn);
72
+ }
73
+ </style>
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div class="secondary-nav">
3
+ <div class="item-wrapper">
4
+ <slot />
5
+ </div>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+
11
+ </script>
12
+
13
+ <style scoped>
14
+ .secondary-nav {
15
+ display: flex;
16
+ flex-direction: column;
17
+ width: 100%;
18
+ margin-bottom: 20px;
19
+ background-color: var(--secondary-nav-background, var(--surface-0, var(--primary-white)));
20
+ color: var(--secondary-nav-text, var(--brand-text, var(--primary-dark)));
21
+ border-radius: 4px;
22
+ box-shadow: var(--secondary-nav-shadow, var(--shadow-6));
23
+ transition: box-shadow 0.3s ease-in-out;
24
+ }
25
+ .secondary-nav:before {
26
+ content: "";
27
+ margin: 4px;
28
+ height: 2px;
29
+ border-radius: 2px;
30
+ background-color: var(--seconadry-nav-accent, var(--brand-0, var(--purple)));
31
+ }
32
+ .secondary-nav .item-wrapper {
33
+ display: flex;
34
+ gap: 4px;
35
+ padding: 12px 24px 0;
36
+ }
37
+ </style>
@@ -0,0 +1,66 @@
1
+ <script setup lang="ts">
2
+ defineProps({
3
+ icon: {
4
+ type: String,
5
+ required: true
6
+ },
7
+ })
8
+ </script>
9
+
10
+
11
+ <template>
12
+ <NuxtLink class="menu-item">
13
+ <div class="menu-item__icon">
14
+ <a-icon :icon />
15
+ </div>
16
+ <span class="menu-item__text">
17
+ <slot />
18
+ </span>
19
+ </NuxtLink>
20
+ </template>
21
+
22
+ <style scoped>
23
+ .menu-item {
24
+ cursor: pointer;
25
+ color: var(--primary-dark);
26
+ display: flex;
27
+ flex-direction: column;
28
+ justify-content: flex-end;
29
+ align-items: center;
30
+ padding: 12px 16px;
31
+ padding-bottom: 4px;
32
+ text-decoration: none;
33
+ }
34
+ .menu-item__text {
35
+ font: var(--font-regular);
36
+ margin-bottom: 4px;
37
+ }
38
+ .menu-item__icon {
39
+ font-size: 32px;
40
+ margin-bottom: 4px;
41
+ }
42
+ .menu-item:after {
43
+ content: "";
44
+ bottom: 0;
45
+ right: 0;
46
+ height: 0;
47
+ width: 16px;
48
+ border-top: 2px solid transparent;
49
+ border-radius: 4px;
50
+ }
51
+ .menu-item:hover, .menu-item:focus, .menu-item.nuxt-link-exact-active, .menu-item.router-link-exact-active {
52
+ background-color: var(--purple-10);
53
+ border-radius: 4px 4px 0px 0px;
54
+ color: var(--purple);
55
+ outline: none;
56
+ }
57
+ .menu-item:hover:after, .menu-item:focus:after, .menu-item.nuxt-link-exact-active:after, .menu-item.router-link-exact-active:after {
58
+ border-top: 2px solid var(--purple);
59
+ }
60
+ .menu-item.nuxt-link-exact-active, .menu-item.router-link-exact-active {
61
+ cursor: default;
62
+ }
63
+ .menu-item.nuxt-link-exact-active .menu-item__text, .menu-item.router-link-exact-active .menu-item__text {
64
+ font: var(--font-medium);
65
+ }
66
+ </style>
@@ -0,0 +1,33 @@
1
+ export declare function useDropdown(): {
2
+ active: any;
3
+ newQuery: any;
4
+ toggleDropdown: ($event: {
5
+ key: string;
6
+ }, optionRef: {
7
+ focus: () => void;
8
+ }[]) => Promise<void>;
9
+ openDropdown: () => void;
10
+ closeDropdown: () => void;
11
+ onClickOutsideHandler: () => void;
12
+ keydownActionsOnTrigger: (event: {
13
+ key: string;
14
+ preventDefault: () => void;
15
+ }, options: any[], optionRef: {
16
+ focus: () => void;
17
+ }[], dropdownTriggerRef: {
18
+ focus: () => void;
19
+ }, searchable: false, inputRef: {
20
+ focus: () => void;
21
+ }) => void;
22
+ handleKeydown: (options: any[], optionIndex: number, event: {
23
+ key: string;
24
+ }, optionRef: {
25
+ focus: () => void;
26
+ }[], triggerRef: {
27
+ focus: () => void;
28
+ }) => number | undefined;
29
+ handleDropdownSearch: (val: string, orgs: any[], optionRef: {
30
+ focus: () => void;
31
+ }[]) => void;
32
+ debouncedFocus: any;
33
+ };
@@ -0,0 +1,195 @@
1
+ import debounce from "lodash/debounce";
2
+ import { ref, nextTick } from "vue";
3
+ export function useDropdown() {
4
+ const active = ref(false);
5
+ let newQuery = ref("");
6
+ async function toggleDropdown($event, optionRef) {
7
+ active.value = !active.value;
8
+ if (active.value && $event.key === "ArrowDown") {
9
+ await nextTick(() => {
10
+ optionRef[0].focus();
11
+ });
12
+ }
13
+ }
14
+ function openDropdown() {
15
+ active.value = true;
16
+ }
17
+ function closeDropdown() {
18
+ active.value = false;
19
+ }
20
+ function onClickOutsideHandler() {
21
+ if (!active.value)
22
+ return;
23
+ closeDropdown();
24
+ }
25
+ function keydownActionsOnTrigger(event, options, optionRef, dropdownTriggerRef, searchable, inputRef) {
26
+ if (event.key !== "Tab") {
27
+ event.preventDefault();
28
+ }
29
+ switch (event.key) {
30
+ case "Tab":
31
+ if (!active.value)
32
+ return;
33
+ closeDropdown();
34
+ break;
35
+ case "ArrowDown":
36
+ nextTick(() => {
37
+ if (active.value && event.key === "ArrowDown") {
38
+ optionRef[0].focus();
39
+ }
40
+ openDropdown();
41
+ });
42
+ break;
43
+ case "ArrowUp":
44
+ openDropdown();
45
+ nextTick(() => {
46
+ if (searchable) {
47
+ return;
48
+ }
49
+ optionRef[0].focus();
50
+ });
51
+ break;
52
+ case " ":
53
+ if (active.value) {
54
+ closeDropdown();
55
+ nextTick(() => {
56
+ dropdownTriggerRef.focus();
57
+ });
58
+ } else {
59
+ openDropdown();
60
+ }
61
+ break;
62
+ case "Enter":
63
+ if (active.value) {
64
+ closeDropdown();
65
+ nextTick(() => {
66
+ dropdownTriggerRef.focus();
67
+ });
68
+ } else {
69
+ nextTick(() => {
70
+ openDropdown();
71
+ });
72
+ }
73
+ break;
74
+ case "Escape":
75
+ closeDropdown();
76
+ dropdownTriggerRef.focus();
77
+ break;
78
+ case "Home":
79
+ openDropdown();
80
+ nextTick(() => {
81
+ optionRef[0].focus();
82
+ });
83
+ break;
84
+ case "End":
85
+ openDropdown();
86
+ nextTick(() => {
87
+ optionRef[options.length - 1].focus();
88
+ });
89
+ break;
90
+ default:
91
+ debounce(handleDropdownSearch(event.key, options, optionRef), 500);
92
+ break;
93
+ }
94
+ }
95
+ function handleKeydown(options, optionIndex, event, optionRef, triggerRef) {
96
+ if (event.altKey && event.key === "ArrowUp") {
97
+ closeDropdown();
98
+ triggerRef.focus();
99
+ return optionIndex;
100
+ }
101
+ switch (event.key) {
102
+ case "Enter":
103
+ nextTick(() => {
104
+ closeDropdown();
105
+ triggerRef.focus();
106
+ return optionIndex;
107
+ });
108
+ break;
109
+ case " ":
110
+ nextTick(() => {
111
+ closeDropdown();
112
+ triggerRef.focus();
113
+ return optionIndex;
114
+ });
115
+ break;
116
+ case "Tab":
117
+ nextTick(() => {
118
+ closeDropdown();
119
+ return optionIndex;
120
+ });
121
+ break;
122
+ case "Escape":
123
+ nextTick(() => {
124
+ closeDropdown();
125
+ triggerRef.focus();
126
+ });
127
+ break;
128
+ case "ArrowDown":
129
+ if (optionIndex === options.length - 1)
130
+ break;
131
+ nextTick(() => {
132
+ optionRef[optionIndex + 1].focus();
133
+ });
134
+ return optionIndex;
135
+ case "ArrowUp":
136
+ if (optionIndex === 0)
137
+ break;
138
+ nextTick(() => {
139
+ optionRef[optionIndex - 1].focus();
140
+ });
141
+ return optionIndex;
142
+ case "Home":
143
+ nextTick(() => {
144
+ optionRef[0].focus();
145
+ });
146
+ return optionIndex;
147
+ case "End":
148
+ nextTick(() => {
149
+ optionRef[options.length - 1].focus();
150
+ });
151
+ return optionIndex;
152
+ case "PageDown": {
153
+ const pageDownIndexToJump = optionIndex + 10 > options.length ? optionIndex + 10 : options.length - 1;
154
+ optionRef[pageDownIndexToJump].focus();
155
+ return optionIndex;
156
+ }
157
+ case "PageUp": {
158
+ const pageUpIndexToJump = optionIndex - 10 < 0 ? optionIndex - 10 : 0;
159
+ optionRef[pageUpIndexToJump].focus();
160
+ return optionIndex;
161
+ }
162
+ default:
163
+ handleDropdownSearch(event.key, options, optionRef);
164
+ break;
165
+ }
166
+ }
167
+ const debouncedFocus = debounce((idx, optionRef) => {
168
+ optionRef[idx].focus();
169
+ }, 500);
170
+ function handleDropdownSearch(val, orgs, optionRef) {
171
+ if (val == "Backspace") {
172
+ newQuery.value = newQuery.value.slice(0, -1);
173
+ return;
174
+ }
175
+ newQuery.value = `${newQuery.value}${val}`;
176
+ const searchIndex = orgs.findIndex(
177
+ (option) => option.name.toLowerCase().includes(newQuery.value.toLowerCase())
178
+ );
179
+ if (searchIndex !== -1) {
180
+ debouncedFocus(searchIndex, optionRef);
181
+ }
182
+ }
183
+ return {
184
+ active,
185
+ newQuery,
186
+ toggleDropdown,
187
+ openDropdown,
188
+ closeDropdown,
189
+ onClickOutsideHandler,
190
+ keydownActionsOnTrigger,
191
+ handleKeydown,
192
+ handleDropdownSearch,
193
+ debouncedFocus
194
+ };
195
+ }
@@ -0,0 +1 @@
1
+ export { type ModuleOptions, default } from './module.js'
@@ -0,0 +1 @@
1
+ export { type ModuleOptions, default } from './module'
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@apptegy/nuxt-navigation",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/types.d.ts",
8
+ "import": "./dist/module.mjs",
9
+ "require": "./dist/module.cjs"
10
+ }
11
+ },
12
+ "main": "./dist/module.cjs",
13
+ "types": "./dist/types.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "prepack": "nuxt-module-build build",
19
+ "dev": "nuxi dev playground",
20
+ "dev:build": "nuxi build playground",
21
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
22
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
23
+ "lint": "eslint .",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest watch",
26
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
27
+ },
28
+ "dependencies": {
29
+ "@nuxt/kit": "^3.12.3"
30
+ },
31
+ "devDependencies": {
32
+ "@nuxt/devtools": "^1.3.9",
33
+ "@nuxt/eslint-config": "^0.3.13",
34
+ "@apptegy/icons": "2.10.0",
35
+ "@nuxt/module-builder": "^0.8.1",
36
+ "@nuxt/schema": "^3.12.3",
37
+ "@nuxt/test-utils": "^3.13.1",
38
+ "@types/node": "^20.14.10",
39
+ "changelogen": "^0.5.5",
40
+ "eslint": "^9.7.0",
41
+ "lodash": "^4.17.15",
42
+ "nuxt": "^3.12.3",
43
+ "sass": "^1.77.8",
44
+ "typescript": "^5.5.3",
45
+ "vitest": "^1.6.0",
46
+ "vue": "^3.4.21",
47
+ "vue-tsc": "^2.0.26"
48
+ }
49
+ }