@mr.dj2u/library-registry 0.2.0 → 0.3.0
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 +3 -0
- package/assets/mds/env/convex.env.example +1 -0
- package/assets/mds/env/firebase.env.example +6 -0
- package/assets/mds/env/supabase.env.example +3 -0
- package/assets/mds/project/auth-base.md +17 -0
- package/assets/mds/project/auth-convex.md +33 -0
- package/assets/mds/project/auth-firebase.md +22 -0
- package/assets/mds/project/auth-supabase.md +46 -0
- package/assets/mds/src/app/(auth)/reset-password.tsx +5 -0
- package/assets/mds/src/app/(auth)/sign-in.tsx +5 -0
- package/assets/mds/src/app/(auth)/sign-up.tsx +5 -0
- package/assets/mds/src/app/legal/updates.tsx +1 -0
- package/assets/mds/src/app/onboarding/complete.tsx +2 -0
- package/assets/mds/src/app/onboarding/features.tsx +1 -0
- package/assets/mds/src/app/onboarding/legal.tsx +2 -0
- package/assets/mds/src/app/onboarding.tsx +1 -1
- package/assets/mds/src/app/settings.tsx +10 -1
- package/assets/mds/src/db/adapter.ts +195 -0
- package/assets/mds/src/db/firebase.ts +77 -0
- package/assets/mds/src/db/index.firebase.ts +19 -0
- package/assets/mds/src/db/index.supabase.ts +22 -0
- package/assets/mds/src/db/supabase.ts +337 -0
- package/assets/mds/src/features/auth/adapters/base-auth-adapter.tsx +82 -0
- package/assets/mds/src/features/auth/adapters/convex-auth-adapter.tsx +156 -0
- package/assets/mds/src/features/auth/adapters/firebase-auth-adapter.tsx +147 -0
- package/assets/mds/src/features/auth/adapters/supabase-auth-adapter.tsx +166 -0
- package/assets/mds/src/features/auth/auth-guard-logic.ts +19 -0
- package/assets/mds/src/features/auth/auth-guard.tsx +77 -0
- package/assets/mds/src/features/auth/auth-provider.tsx +60 -0
- package/assets/mds/src/features/auth/auth-screen.tsx +265 -0
- package/assets/mds/src/features/auth/auth-types.ts +45 -0
- package/assets/mds/src/features/exposition/data-screen.tsx +4 -2
- package/assets/mds/src/features/exposition/expo-sdk-56-screen.tsx +119 -76
- package/assets/mds/src/features/exposition/exposition-screen.tsx +10 -11
- package/assets/mds/src/features/exposition/stylist-screen.tsx +62 -11
- package/assets/mds/src/features/legal/legal-acceptance-adapter.ts +190 -0
- package/assets/mds/src/features/legal/legal-acceptance-config.ts +79 -0
- package/assets/mds/src/features/legal/legal-agreement-screen.tsx +9 -4
- package/assets/mds/src/features/legal/legal-document-modal.tsx +7 -3
- package/assets/mds/src/features/legal/legal-document-view.tsx +1 -0
- package/assets/mds/src/features/legal/legal-documents.ts +17 -3
- package/assets/mds/src/features/legal/legal-update-screen.tsx +297 -0
- package/assets/mds/src/features/legal/use-legal-acceptance.ts +1 -38
- package/assets/mds/src/features/onboarding/complete-screen.tsx +138 -0
- package/assets/mds/src/features/onboarding/features-screen.tsx +129 -0
- package/assets/mds/src/features/onboarding/legal-review-screen.tsx +242 -0
- package/assets/mds/src/features/onboarding/onboarding-config-with-legal.ts +104 -0
- package/assets/mds/src/features/onboarding/onboarding-config.ts +104 -0
- package/assets/mds/src/features/onboarding/onboarding-persistence-sync.tsx +1 -0
- package/assets/mds/src/features/onboarding/welcome-screen.tsx +130 -0
- package/assets/mds/src/features/onboarding-state/adapters/memory-onboarding-state-adapter.ts +15 -0
- package/assets/mds/src/features/onboarding-state/adapters/supabase-onboarding-state-adapter.ts +45 -0
- package/assets/mds/src/features/onboarding-state/adapters/zustand-onboarding-state-adapter.ts +16 -0
- package/assets/mds/src/features/onboarding-state/adapters/zustand-supabase-onboarding-state-adapter.ts +53 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-core.ts +108 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-memory.ts +106 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-supabase.ts +246 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-types.ts +64 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-zustand-supabase.ts +120 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state-zustand.ts +71 -0
- package/assets/mds/src/features/onboarding-state/onboarding-state.ts +22 -0
- package/assets/mds/src/features/onboarding-state/onboarding-store.ts +39 -0
- package/assets/mds/src/features/settings/settings-screen-logic.ts +122 -0
- package/assets/mds/src/features/settings/settings-screen.tsx +274 -28
- package/assets/mds/src/services/convex.ts +40 -0
- package/assets/mds/src/services/firebase.ts +70 -0
- package/assets/mds/src/services/supabase.ts +50 -0
- package/assets/mds/src/theme/color-utils.ts +42 -0
- package/assets/mds/src/theme/provider.tsx +15 -5
- package/assets/mds/src/types/database.ts +13 -0
- package/assets/mds/supabase/migrations/0001_mds_auth_onboarding.sql +107 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +444 -29
- package/dist/catalog.js.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/assets/mds/src/app/onboarding/account-setup.tsx +0 -1
- package/assets/mds/src/app/onboarding/agreement.tsx +0 -1
- package/assets/mds/src/app/onboarding/terms.tsx +0 -1
- package/assets/mds/src/features/onboarding/account-setup-screen.tsx +0 -54
- package/assets/mds/src/features/onboarding/agreement-screen.tsx +0 -6
- package/assets/mds/src/features/onboarding/components/legal-document-view.tsx +0 -103
- package/assets/mds/src/features/onboarding/legal-documents.ts +0 -80
- package/assets/mds/src/features/onboarding/onboarding-screen.tsx +0 -167
- package/assets/mds/src/features/onboarding/terms-screen.tsx +0 -6
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
|
+
import { AppState } from 'react-native';
|
|
3
|
+
import { createClient } from '@supabase/supabase-js';
|
|
4
|
+
|
|
5
|
+
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL;
|
|
6
|
+
const supabasePublishableKey =
|
|
7
|
+
process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY ??
|
|
8
|
+
process.env.EXPO_PUBLIC_SUPABASE_KEY ??
|
|
9
|
+
process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY;
|
|
10
|
+
const isServerRender = typeof window === 'undefined';
|
|
11
|
+
const supabaseStorage = {
|
|
12
|
+
getItem: (key: string) => (isServerRender ? Promise.resolve(null) : AsyncStorage.getItem(key)),
|
|
13
|
+
setItem: (key: string, value: string) =>
|
|
14
|
+
isServerRender ? Promise.resolve() : AsyncStorage.setItem(key, value),
|
|
15
|
+
removeItem: (key: string) => (isServerRender ? Promise.resolve() : AsyncStorage.removeItem(key)),
|
|
16
|
+
};
|
|
17
|
+
export const supabase =
|
|
18
|
+
supabaseUrl && supabasePublishableKey
|
|
19
|
+
? createClient(supabaseUrl, supabasePublishableKey, {
|
|
20
|
+
auth: {
|
|
21
|
+
storage: supabaseStorage,
|
|
22
|
+
autoRefreshToken: !isServerRender,
|
|
23
|
+
persistSession: !isServerRender,
|
|
24
|
+
detectSessionInUrl: false,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
: null;
|
|
28
|
+
|
|
29
|
+
if (supabase) {
|
|
30
|
+
AppState.addEventListener('change', (state) => {
|
|
31
|
+
if (state === 'active') {
|
|
32
|
+
supabase.auth.startAutoRefresh();
|
|
33
|
+
} else {
|
|
34
|
+
supabase.auth.stopAutoRefresh();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getSupabaseClient(): NonNullable<typeof supabase> {
|
|
40
|
+
if (!supabase) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
'Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY before using Supabase. EXPO_PUBLIC_SUPABASE_KEY and EXPO_PUBLIC_SUPABASE_ANON_KEY are accepted as fallbacks for older projects.'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return supabase;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function assertSupabaseConfigured(): void {
|
|
49
|
+
void getSupabaseClient();
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function parseHexColor(color: string): [number, number, number] | null {
|
|
2
|
+
const normalized = color.trim().replace(/^#/, '');
|
|
3
|
+
|
|
4
|
+
if (/^[0-9a-f]{3}$/i.test(normalized)) {
|
|
5
|
+
return normalized.split('').map((value) => parseInt(`${value}${value}`, 16)) as [
|
|
6
|
+
number,
|
|
7
|
+
number,
|
|
8
|
+
number,
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (/^[0-9a-f]{6}$/i.test(normalized)) {
|
|
13
|
+
return [
|
|
14
|
+
parseInt(normalized.slice(0, 2), 16),
|
|
15
|
+
parseInt(normalized.slice(2, 4), 16),
|
|
16
|
+
parseInt(normalized.slice(4, 6), 16),
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function toLinearChannel(value: number): number {
|
|
24
|
+
const channel = value / 255;
|
|
25
|
+
return channel <= 0.03928 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getReadableTextColor(
|
|
29
|
+
backgroundColor: string,
|
|
30
|
+
darkText = '#111827',
|
|
31
|
+
lightText = '#ffffff',
|
|
32
|
+
): string {
|
|
33
|
+
const rgb = parseHexColor(backgroundColor);
|
|
34
|
+
if (!rgb) {
|
|
35
|
+
return lightText;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const [red, green, blue] = rgb.map(toLinearChannel);
|
|
39
|
+
const luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
|
40
|
+
|
|
41
|
+
return luminance > 0.45 ? darkText : lightText;
|
|
42
|
+
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type ReactNode,
|
|
8
8
|
type SetStateAction,
|
|
9
9
|
} from 'react';
|
|
10
|
-
import { useColorScheme } from 'react-native';
|
|
10
|
+
import { Appearance, useColorScheme } from 'react-native';
|
|
11
11
|
|
|
12
12
|
import defaultThemeTokens, {
|
|
13
13
|
type StylistColorPalette,
|
|
@@ -25,10 +25,17 @@ export type AppThemeColorOverrides = Partial<
|
|
|
25
25
|
Record<StylistColorScheme, Partial<StylistColorPalette>>
|
|
26
26
|
>;
|
|
27
27
|
|
|
28
|
+
export function readSystemScheme(): StylistColorScheme | null {
|
|
29
|
+
const scheme = Appearance.getColorScheme();
|
|
30
|
+
return scheme === 'light' || scheme === 'dark' ? scheme : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const initialSystemScheme = readSystemScheme() ?? 'light';
|
|
34
|
+
|
|
28
35
|
const AppThemeContext = createContext<AppThemeValue>({
|
|
29
36
|
...defaultThemeTokens,
|
|
30
|
-
activeScheme:
|
|
31
|
-
activeColors: defaultThemeTokens.colors[
|
|
37
|
+
activeScheme: initialSystemScheme,
|
|
38
|
+
activeColors: defaultThemeTokens.colors[initialSystemScheme],
|
|
32
39
|
});
|
|
33
40
|
const AppThemeSetterContext = createContext<Dispatch<SetStateAction<StylistThemeTokens>> | null>(
|
|
34
41
|
null
|
|
@@ -42,10 +49,13 @@ function resolveActiveScheme(
|
|
|
42
49
|
if (preference === 'light' || preference === 'dark') {
|
|
43
50
|
return preference;
|
|
44
51
|
}
|
|
45
|
-
if (preference === '
|
|
52
|
+
if (preference === 'preview') {
|
|
53
|
+
return theme.colorSystem.previewScheme;
|
|
54
|
+
}
|
|
55
|
+
if (systemScheme === 'light' || systemScheme === 'dark') {
|
|
46
56
|
return systemScheme;
|
|
47
57
|
}
|
|
48
|
-
return
|
|
58
|
+
return readSystemScheme() ?? 'light';
|
|
49
59
|
}
|
|
50
60
|
|
|
51
61
|
export function AppThemeProvider({
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DatabaseSchema } from '../db/adapter';
|
|
2
|
+
|
|
3
|
+
export type DemoGuestbookRow = {
|
|
4
|
+
id: number;
|
|
5
|
+
user_id: string;
|
|
6
|
+
display_name: string;
|
|
7
|
+
message: string;
|
|
8
|
+
created_at: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type AppDatabase = {
|
|
12
|
+
mds_demo_guestbook_comments: DemoGuestbookRow;
|
|
13
|
+
} & DatabaseSchema;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
create table if not exists public.user_onboarding_state (
|
|
2
|
+
user_id uuid primary key references auth.users(id) on delete cascade,
|
|
3
|
+
flow_id text not null default 'mds/onboarding',
|
|
4
|
+
flow_version integer not null default 1,
|
|
5
|
+
status text not null default 'not_started',
|
|
6
|
+
current_step text,
|
|
7
|
+
completed_at timestamptz,
|
|
8
|
+
metadata jsonb not null default '{}'::jsonb,
|
|
9
|
+
created_at timestamptz not null default now(),
|
|
10
|
+
updated_at timestamptz not null default now()
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
alter table public.user_onboarding_state
|
|
14
|
+
add column if not exists flow_id text not null default 'mds/onboarding',
|
|
15
|
+
add column if not exists flow_version integer not null default 1,
|
|
16
|
+
add column if not exists status text not null default 'not_started',
|
|
17
|
+
add column if not exists current_step text,
|
|
18
|
+
add column if not exists completed_at timestamptz,
|
|
19
|
+
add column if not exists metadata jsonb not null default '{}'::jsonb,
|
|
20
|
+
add column if not exists created_at timestamptz not null default now(),
|
|
21
|
+
add column if not exists updated_at timestamptz not null default now();
|
|
22
|
+
|
|
23
|
+
alter table public.user_onboarding_state enable row level security;
|
|
24
|
+
|
|
25
|
+
drop policy if exists "Users can read their onboarding state" on public.user_onboarding_state;
|
|
26
|
+
create policy "Users can read their onboarding state"
|
|
27
|
+
on public.user_onboarding_state
|
|
28
|
+
for select
|
|
29
|
+
to authenticated
|
|
30
|
+
using (auth.uid() = user_id);
|
|
31
|
+
|
|
32
|
+
drop policy if exists "Users can upsert their onboarding state" on public.user_onboarding_state;
|
|
33
|
+
drop policy if exists "Users can insert their onboarding state" on public.user_onboarding_state;
|
|
34
|
+
create policy "Users can insert their onboarding state"
|
|
35
|
+
on public.user_onboarding_state
|
|
36
|
+
for insert
|
|
37
|
+
to authenticated
|
|
38
|
+
with check (auth.uid() = user_id);
|
|
39
|
+
|
|
40
|
+
drop policy if exists "Users can update their onboarding state" on public.user_onboarding_state;
|
|
41
|
+
create policy "Users can update their onboarding state"
|
|
42
|
+
on public.user_onboarding_state
|
|
43
|
+
for update
|
|
44
|
+
to authenticated
|
|
45
|
+
using (auth.uid() = user_id)
|
|
46
|
+
with check (auth.uid() = user_id);
|
|
47
|
+
|
|
48
|
+
create table if not exists public.user_legal_acceptances (
|
|
49
|
+
id uuid primary key default gen_random_uuid(),
|
|
50
|
+
user_id uuid not null references auth.users(id) on delete cascade,
|
|
51
|
+
document_id text not null,
|
|
52
|
+
document_version text not null,
|
|
53
|
+
acceptance_version text,
|
|
54
|
+
flow_id text,
|
|
55
|
+
accepted_at timestamptz not null default now(),
|
|
56
|
+
metadata jsonb not null default '{}'::jsonb,
|
|
57
|
+
unique (user_id, document_id, document_version)
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
alter table public.user_legal_acceptances
|
|
61
|
+
add column if not exists document_id text not null default 'legacy',
|
|
62
|
+
add column if not exists document_version text not null default 'legacy',
|
|
63
|
+
add column if not exists acceptance_version text,
|
|
64
|
+
add column if not exists flow_id text,
|
|
65
|
+
add column if not exists accepted_at timestamptz not null default now(),
|
|
66
|
+
add column if not exists metadata jsonb not null default '{}'::jsonb;
|
|
67
|
+
|
|
68
|
+
do $$
|
|
69
|
+
begin
|
|
70
|
+
if exists (
|
|
71
|
+
select 1
|
|
72
|
+
from information_schema.columns
|
|
73
|
+
where table_schema = 'public'
|
|
74
|
+
and table_name = 'user_legal_acceptances'
|
|
75
|
+
and column_name = 'acceptance_version'
|
|
76
|
+
) then
|
|
77
|
+
update public.user_legal_acceptances
|
|
78
|
+
set document_version = acceptance_version
|
|
79
|
+
where document_version = 'legacy'
|
|
80
|
+
and acceptance_version is not null;
|
|
81
|
+
|
|
82
|
+
alter table public.user_legal_acceptances
|
|
83
|
+
alter column acceptance_version drop not null;
|
|
84
|
+
end if;
|
|
85
|
+
end $$;
|
|
86
|
+
|
|
87
|
+
create unique index if not exists user_legal_acceptances_user_document_version_idx
|
|
88
|
+
on public.user_legal_acceptances (user_id, document_id, document_version);
|
|
89
|
+
|
|
90
|
+
alter table public.user_legal_acceptances enable row level security;
|
|
91
|
+
|
|
92
|
+
drop policy if exists "Users can read their legal acceptances" on public.user_legal_acceptances;
|
|
93
|
+
create policy "Users can read their legal acceptances"
|
|
94
|
+
on public.user_legal_acceptances
|
|
95
|
+
for select
|
|
96
|
+
to authenticated
|
|
97
|
+
using (auth.uid() = user_id);
|
|
98
|
+
|
|
99
|
+
drop policy if exists "Users can record their legal acceptances" on public.user_legal_acceptances;
|
|
100
|
+
create policy "Users can record their legal acceptances"
|
|
101
|
+
on public.user_legal_acceptances
|
|
102
|
+
for insert
|
|
103
|
+
to authenticated
|
|
104
|
+
with check (auth.uid() = user_id);
|
|
105
|
+
|
|
106
|
+
grant select, insert, update on public.user_onboarding_state to authenticated;
|
|
107
|
+
grant select, insert on public.user_legal_acceptances to authenticated;
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMV,WAAW,EAKZ,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMV,WAAW,EAKZ,MAAM,YAAY,CAAC;AA8sEpB,eAAO,MAAM,cAAc,EAAE,SAAS,WAAW,EAKhD,CAAC"}
|