or3-provider-basic-auth 0.0.8 → 0.0.9

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/README.md CHANGED
@@ -90,6 +90,11 @@ Strict-mode behavior:
90
90
  | `src/runtime/plugins/auth-status.client.ts` | Client auth-status resolver + silent-refresh recovery |
91
91
  | `src/runtime/components/*.client.vue` | Provider-owned auth UI (modals, user menu, sidebar button, lock page) |
92
92
 
93
+ The registered sidebar auth adapter accepts `layout="rail"` (default) and
94
+ `layout="more-sheet"`. In the More sheet it renders Account/Login with the
95
+ host's shared full-width `.more-row` structure, while keeping the existing
96
+ popover and modal behavior.
97
+
93
98
  ## Troubleshooting
94
99
 
95
100
  - `Authentication provider is not configured`
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "or3-provider-basic-auth",
3
3
  "configKey": "or3-provider-basic-auth",
4
- "version": "0.0.8",
4
+ "version": "0.0.9",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -84,7 +84,8 @@
84
84
  <script setup>
85
85
  import { computed, reactive, ref } from "vue";
86
86
  const modalUi = {
87
- content: "sm:max-w-[400px]"
87
+ overlay: "basic-auth-modal-overlay",
88
+ content: "basic-auth-modal-content sm:max-w-[400px]"
88
89
  };
89
90
  const props = defineProps({
90
91
  modelValue: { type: Boolean, required: true },
@@ -113,7 +113,8 @@
113
113
  <script setup>
114
114
  import { computed, reactive, ref } from "vue";
115
115
  const modalUi = {
116
- content: "sm:max-w-[420px]"
116
+ overlay: "basic-auth-modal-overlay",
117
+ content: "basic-auth-modal-content sm:max-w-[420px]"
117
118
  };
118
119
  const props = defineProps({
119
120
  modelValue: { type: Boolean, required: true }
@@ -85,7 +85,8 @@
85
85
  <script setup>
86
86
  import { computed, reactive, ref } from "vue";
87
87
  const modalUi = {
88
- content: "sm:max-w-[380px]"
88
+ overlay: "basic-auth-modal-overlay",
89
+ content: "basic-auth-modal-content sm:max-w-[380px]"
89
90
  };
90
91
  const props = defineProps({
91
92
  modelValue: { type: Boolean, required: true }
@@ -1,6 +1,9 @@
1
+ import { type AuthUiLayout } from '../lib/auth-ui-layout.js';
1
2
  type __VLS_Props = {
2
3
  email?: string;
3
4
  displayName?: string;
5
+ /** Explicit host layout — preferred over inject (cross-package inject can miss). */
6
+ layout?: AuthUiLayout;
4
7
  };
5
8
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
9
  "signed-out": () => any;
@@ -3,9 +3,31 @@
3
3
  v-model:open="isOpen"
4
4
  portal
5
5
  :content="popoverContent"
6
- :ui="{ content: 'z-[280] max-w-[240px] p-0 border-none bg-transparent shadow-none' }"
6
+ :ui="{ content: 'basic-auth-account-popover max-w-[240px] p-0 border-none bg-transparent shadow-none' }"
7
7
  >
8
+ <!-- More sheet: identical anatomy to System .more-row -->
9
+ <button
10
+ v-if="isMoreSheetLayout"
11
+ type="button"
12
+ class="more-row"
13
+ aria-label="Account menu"
14
+ >
15
+ <span class="more-row-icon more-row-icon--admin" aria-hidden="true">
16
+ <UIcon name="lucide:user" />
17
+ </span>
18
+ <span class="more-row-copy">
19
+ <span class="more-row-label">Account</span>
20
+ <span class="more-row-desc">Manage your profile & settings</span>
21
+ </span>
22
+ <UIcon
23
+ name="lucide:chevron-right"
24
+ class="more-row-chevron"
25
+ aria-hidden="true"
26
+ />
27
+ </button>
28
+
8
29
  <UButton
30
+ v-else
9
31
  v-bind="triggerButtonProps"
10
32
  type="button"
11
33
  aria-label="Account menu"
@@ -13,7 +35,9 @@
13
35
  <template #default>
14
36
  <span class="flex flex-col items-center gap-1 w-full">
15
37
  <UIcon name="lucide:user" class="h-[18px] w-[18px]" />
16
- <span class="sidebar-rail-caption text-[7px] uppercase tracking-wider whitespace-nowrap">
38
+ <span
39
+ class="sidebar-rail-caption text-[7px] uppercase tracking-wider whitespace-nowrap"
40
+ >
17
41
  Account
18
42
  </span>
19
43
  </span>
@@ -24,17 +48,22 @@
24
48
  <div
25
49
  class="basic-auth-account-menu w-[220px] rounded-[var(--md-border-radius)] border-[length:var(--md-border-width)] border-[color:var(--md-border-color)] bg-[var(--md-surface)] overflow-hidden theme-shadow"
26
50
  >
27
- <!-- User identity section -->
28
51
  <div class="px-4 pt-4 pb-3">
29
52
  <div class="flex items-center gap-3">
30
- <div class="flex items-center justify-center w-8 h-8 rounded-full bg-[var(--md-success)]/15 text-[var(--md-success)] shrink-0">
53
+ <div
54
+ class="flex items-center justify-center w-8 h-8 rounded-full bg-[var(--md-success)]/15 text-[var(--md-success)] shrink-0"
55
+ >
31
56
  <UIcon name="lucide:user" class="w-4 h-4" />
32
57
  </div>
33
58
  <div class="min-w-0">
34
- <p class="text-[10px] uppercase tracking-wider text-[var(--md-on-surface)]/50 mb-0.5">
59
+ <p
60
+ class="text-[10px] uppercase tracking-wider text-[var(--md-on-surface)]/50 mb-0.5"
61
+ >
35
62
  Signed in as
36
63
  </p>
37
- <p class="text-xs font-medium text-[var(--md-on-surface)] break-all leading-tight">
64
+ <p
65
+ class="text-xs font-medium text-[var(--md-on-surface)] break-all leading-tight"
66
+ >
38
67
  {{ email }}
39
68
  </p>
40
69
  </div>
@@ -43,14 +72,16 @@
43
72
 
44
73
  <div class="h-[var(--md-border-width)] bg-[var(--md-border-color)] mx-3" />
45
74
 
46
- <!-- Actions -->
47
75
  <div class="p-2 space-y-1">
48
76
  <button
49
77
  type="button"
50
78
  class="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-[var(--md-on-surface)] rounded-[var(--md-border-radius)] hover:bg-[var(--md-surface-hover)] active:bg-[var(--md-surface-active)] transition-colors text-left"
51
79
  @click="onChangePassword"
52
80
  >
53
- <UIcon name="lucide:key-round" class="w-4 h-4 text-[var(--md-on-surface)]/60 shrink-0" />
81
+ <UIcon
82
+ name="lucide:key-round"
83
+ class="w-4 h-4 text-[var(--md-on-surface)]/60 shrink-0"
84
+ />
54
85
  Change Password
55
86
  </button>
56
87
 
@@ -74,9 +105,13 @@ import { computed, inject, ref, unref } from "vue";
74
105
  import {
75
106
  AUTH_UI_POPOVER_CONTENT_KEY
76
107
  } from "../lib/auth-ui-popover";
77
- defineProps({
108
+ import {
109
+ AUTH_UI_LAYOUT_KEY
110
+ } from "../lib/auth-ui-layout";
111
+ const props = defineProps({
78
112
  email: { type: String, required: false },
79
- displayName: { type: String, required: false }
113
+ displayName: { type: String, required: false },
114
+ layout: { type: String, required: false }
80
115
  });
81
116
  const emit = defineEmits(["signed-out", "change-password"]);
82
117
  const isOpen = ref(false);
@@ -91,6 +126,10 @@ const injectedPopoverContent = inject(
91
126
  AUTH_UI_POPOVER_CONTENT_KEY,
92
127
  null
93
128
  );
129
+ const injectedLayout = inject(AUTH_UI_LAYOUT_KEY, null);
130
+ const isMoreSheetLayout = computed(
131
+ () => props.layout === "more-sheet" || (injectedLayout ? unref(injectedLayout) : "rail") === "more-sheet"
132
+ );
94
133
  const popoverContent = computed(() => ({
95
134
  ...DEFAULT_POPOVER_CONTENT,
96
135
  ...injectedPopoverContent ? unref(injectedPopoverContent) : null
@@ -121,3 +160,7 @@ async function onSignOut() {
121
160
  }
122
161
  }
123
162
  </script>
163
+
164
+ <style>
165
+ .basic-auth-account-popover,[data-reka-popper-content-wrapper]:has(.basic-auth-account-menu){z-index:100!important}
166
+ </style>
@@ -1,6 +1,9 @@
1
+ import { type AuthUiLayout } from '../lib/auth-ui-layout.js';
1
2
  type __VLS_Props = {
2
3
  email?: string;
3
4
  displayName?: string;
5
+ /** Explicit host layout — preferred over inject (cross-package inject can miss). */
6
+ layout?: AuthUiLayout;
4
7
  };
5
8
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
9
  "signed-out": () => any;
@@ -1,2 +1,7 @@
1
- declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ import { type AuthUiLayout } from '../lib/auth-ui-layout.js';
2
+ type __VLS_Props = {
3
+ /** Explicit host layout — preferred over inject (cross-package inject can miss). */
4
+ layout?: AuthUiLayout;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
7
  export default _default;
@@ -4,10 +4,32 @@
4
4
  v-if="isSignedIn"
5
5
  :email="sessionUser?.email"
6
6
  :display-name="sessionUser?.displayName"
7
+ :layout="resolvedLayout"
7
8
  @signed-out="onSignedOut"
8
9
  @change-password="changePasswordModalOpen = true"
9
10
  />
10
11
 
12
+ <button
13
+ v-else-if="isMoreSheetLayout"
14
+ type="button"
15
+ class="more-row"
16
+ aria-label="Login"
17
+ @click="signInModalOpen = true"
18
+ >
19
+ <span class="more-row-icon more-row-icon--admin" aria-hidden="true">
20
+ <UIcon name="lucide:log-in" />
21
+ </span>
22
+ <span class="more-row-copy">
23
+ <span class="more-row-label">Login</span>
24
+ <span class="more-row-desc">Manage your profile & settings</span>
25
+ </span>
26
+ <UIcon
27
+ name="lucide:chevron-right"
28
+ class="more-row-chevron"
29
+ aria-hidden="true"
30
+ />
31
+ </button>
32
+
11
33
  <UButton
12
34
  v-else
13
35
  v-bind="loginButtonProps"
@@ -18,7 +40,9 @@
18
40
  <template #default>
19
41
  <span class="flex flex-col items-center gap-1 w-full">
20
42
  <UIcon name="lucide:log-in" class="h-[18px] w-[18px]" />
21
- <span class="sidebar-rail-caption text-[7px] uppercase tracking-wider whitespace-nowrap">
43
+ <span
44
+ class="sidebar-rail-caption text-[7px] uppercase tracking-wider whitespace-nowrap"
45
+ >
22
46
  Login
23
47
  </span>
24
48
  </span>
@@ -45,14 +69,20 @@
45
69
  </template>
46
70
 
47
71
  <script setup>
48
- import { computed, nextTick, onMounted, ref } from "vue";
72
+ import { computed, inject, nextTick, onMounted, ref, unref } from "vue";
49
73
  import { useRuntimeConfig } from "#imports";
50
74
  import { BASIC_AUTH_PROVIDER_ID } from "../lib/constants";
75
+ import {
76
+ AUTH_UI_LAYOUT_KEY
77
+ } from "../lib/auth-ui-layout";
51
78
  import { silentRefreshOnce } from "../lib/silent-refresh.client";
52
79
  import BasicAuthSignInModal from "./BasicAuthSignInModal.client.vue";
53
80
  import BasicAuthRegisterModal from "./BasicAuthRegisterModal.client.vue";
54
81
  import BasicAuthUserMenu from "./BasicAuthUserMenu.client.vue";
55
82
  import BasicAuthChangePasswordModal from "./BasicAuthChangePasswordModal.client.vue";
83
+ const props = defineProps({
84
+ layout: { type: String, required: false }
85
+ });
56
86
  const runtimeConfig = useRuntimeConfig();
57
87
  const signInModalOpen = ref(false);
58
88
  const registerModalOpen = ref(false);
@@ -95,6 +125,16 @@ const isSignedIn = computed(
95
125
  () => session.value?.authenticated === true && session.value.provider === BASIC_AUTH_PROVIDER_ID
96
126
  );
97
127
  const sessionUser = computed(() => session.value?.user);
128
+ const injectedLayout = inject(AUTH_UI_LAYOUT_KEY, null);
129
+ const resolvedLayout = computed(() => {
130
+ if (props.layout === "more-sheet" || props.layout === "rail") {
131
+ return props.layout;
132
+ }
133
+ return injectedLayout ? unref(injectedLayout) : "rail";
134
+ });
135
+ const isMoreSheetLayout = computed(
136
+ () => resolvedLayout.value === "more-sheet"
137
+ );
98
138
  const loginButtonProps = {
99
139
  block: true,
100
140
  variant: "ghost",
@@ -135,3 +175,7 @@ onMounted(() => {
135
175
  void refreshSession();
136
176
  });
137
177
  </script>
178
+
179
+ <style>
180
+ .basic-auth-modal-content,.basic-auth-modal-overlay{z-index:100!important}
181
+ </style>
@@ -1,2 +1,7 @@
1
- declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
1
+ import { type AuthUiLayout } from '../lib/auth-ui-layout.js';
2
+ type __VLS_Props = {
3
+ /** Explicit host layout — preferred over inject (cross-package inject can miss). */
4
+ layout?: AuthUiLayout;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
2
7
  export default _default;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Host apps can inject a layout mode so auth triggers match the surface
3
+ * (sidebar rail tiles vs mobile More sheet list rows).
4
+ */
5
+ export type AuthUiLayout = 'rail' | 'more-sheet';
6
+ /** String key so host app + provider package can share without a linked import. */
7
+ export declare const AUTH_UI_LAYOUT_KEY = "or3:auth-ui-layout";
@@ -0,0 +1 @@
1
+ export const AUTH_UI_LAYOUT_KEY = "or3:auth-ui-layout";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "or3-provider-basic-auth",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Saluana/or3-provider-basic-auth.git"