linked-data-browser 0.0.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.
Files changed (91) hide show
  1. package/.eslintrc.js +13 -0
  2. package/.ldo/profile.context.ts +459 -0
  3. package/.ldo/profile.schema.ts +751 -0
  4. package/.ldo/profile.shapeTypes.ts +71 -0
  5. package/.ldo/profile.typings.ts +295 -0
  6. package/.prettierignore +6 -0
  7. package/.prettierrc +10 -0
  8. package/.shapes/profile.shex +121 -0
  9. package/README.md +3 -0
  10. package/app/index.tsx +25 -0
  11. package/app.json +37 -0
  12. package/assets/images/adaptive-icon.png +0 -0
  13. package/assets/images/favicon.png +0 -0
  14. package/assets/images/icon.png +0 -0
  15. package/assets/images/splash.png +0 -0
  16. package/babel.config.js +6 -0
  17. package/components/DataBrowser.tsx +57 -0
  18. package/components/ResourceView.tsx +14 -0
  19. package/components/TargetResourceProvider.tsx +128 -0
  20. package/components/ThemeProvider.tsx +123 -0
  21. package/components/nav/DialogProvider.tsx +140 -0
  22. package/components/nav/Layout.tsx +118 -0
  23. package/components/nav/header/AddressBox.tsx +126 -0
  24. package/components/nav/header/AvatarMenu.tsx +62 -0
  25. package/components/nav/header/Header.tsx +28 -0
  26. package/components/nav/header/SignInMenu.tsx +126 -0
  27. package/components/nav/header/ThemeToggleMenu.tsx +34 -0
  28. package/components/nav/header/ViewMenu.tsx +88 -0
  29. package/components/nav/useValidView.tsx +51 -0
  30. package/components/nav/utilityResourceViews/ErrorMessageResourceView.tsx +26 -0
  31. package/components/ui/avatar.tsx +53 -0
  32. package/components/ui/button.tsx +88 -0
  33. package/components/ui/card.tsx +101 -0
  34. package/components/ui/dialog.tsx +159 -0
  35. package/components/ui/dropdown-menu.tsx +275 -0
  36. package/components/ui/input.tsx +25 -0
  37. package/components/ui/label.tsx +34 -0
  38. package/components/ui/navigation-menu.tsx +200 -0
  39. package/components/ui/popover.tsx +45 -0
  40. package/components/ui/progress.tsx +79 -0
  41. package/components/ui/radio-group.tsx +59 -0
  42. package/components/ui/separator.tsx +27 -0
  43. package/components/ui/switch.tsx +105 -0
  44. package/components/ui/text.tsx +30 -0
  45. package/components/ui/tooltip.tsx +46 -0
  46. package/components.json +7 -0
  47. package/global.css +61 -0
  48. package/index.js +12 -0
  49. package/lib/android-navigation-bar.ts +11 -0
  50. package/lib/constants.ts +18 -0
  51. package/lib/icons/ArrowRight.tsx +4 -0
  52. package/lib/icons/Check.tsx +4 -0
  53. package/lib/icons/ChevronDown.tsx +4 -0
  54. package/lib/icons/ChevronRight.tsx +4 -0
  55. package/lib/icons/ChevronUp.tsx +4 -0
  56. package/lib/icons/ChevronsRight.tsx +4 -0
  57. package/lib/icons/CircleSlash.tsx +4 -0
  58. package/lib/icons/CircleX.tsx +4 -0
  59. package/lib/icons/Code.tsx +4 -0
  60. package/lib/icons/EllipsisVertical.tsx +4 -0
  61. package/lib/icons/EyeOff.tsx +4 -0
  62. package/lib/icons/File.tsx +4 -0
  63. package/lib/icons/Folder.tsx +4 -0
  64. package/lib/icons/Folders.tsx +4 -0
  65. package/lib/icons/Info.tsx +4 -0
  66. package/lib/icons/MonitorSmartphone.tsx +4 -0
  67. package/lib/icons/MoonStar.tsx +4 -0
  68. package/lib/icons/OctagonX.tsx +4 -0
  69. package/lib/icons/RefreshCw.tsx +4 -0
  70. package/lib/icons/ShieldX.tsx +4 -0
  71. package/lib/icons/Sun.tsx +4 -0
  72. package/lib/icons/TextCursorInput.tsx +4 -0
  73. package/lib/icons/Trash.tsx +4 -0
  74. package/lib/icons/ViewIcon.tsx +4 -0
  75. package/lib/icons/X.tsx +4 -0
  76. package/lib/icons/iconWithClassName.ts +14 -0
  77. package/lib/utils.ts +6 -0
  78. package/metro.config.js +6 -0
  79. package/nativewind-env.d.ts +1 -0
  80. package/package.json +89 -0
  81. package/resourceViews/Container/ContainerConfig.tsx +13 -0
  82. package/resourceViews/Container/ContainerView.tsx +148 -0
  83. package/resourceViews/RawCode/RawCodeConfig.tsx +11 -0
  84. package/resourceViews/RawCode/RawCodeEditor.tsx +37 -0
  85. package/resourceViews/RawCode/RawCodeView.tsx +67 -0
  86. package/scripts/adjust-server-paths.js +37 -0
  87. package/scripts/adjust-standalone-paths.js +28 -0
  88. package/tailwind.config.js +69 -0
  89. package/test-server/server-config.json +75 -0
  90. package/test-server/solid-css-seed.json +11 -0
  91. package/tsconfig.json +19 -0
@@ -0,0 +1,14 @@
1
+ import type { LucideIcon } from 'lucide-react-native';
2
+ import { cssInterop } from 'nativewind';
3
+
4
+ export function iconWithClassName(icon: LucideIcon) {
5
+ cssInterop(icon, {
6
+ className: {
7
+ target: 'style',
8
+ nativeStyleToProp: {
9
+ color: true,
10
+ opacity: true,
11
+ },
12
+ },
13
+ });
14
+ }
package/lib/utils.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,6 @@
1
+ const { getDefaultConfig } = require('expo/metro-config');
2
+ const { withNativeWind } = require('nativewind/metro');
3
+
4
+ const config = getDefaultConfig(__dirname);
5
+
6
+ module.exports = withNativeWind(config, { input: './global.css' });
@@ -0,0 +1 @@
1
+ /// <reference types="nativewind/types" />
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "linked-data-browser",
3
+ "main": "index.js",
4
+ "version": "0.0.0",
5
+ "scripts": {
6
+ "dev:ios": "expo start -c --ios",
7
+ "dev:web": "concurrently \"npm run solid-server\" \"expo start -c --web\"",
8
+ "dev:android": "expo start -c --android",
9
+ "dev:server-hosted": "concurrently \"npm run solid-server\" \"npm run build:server:watch\"",
10
+ "clean": "rm -rf .expo node_modules dist-standalone dist-server",
11
+ "postinstall": "npx tailwindcss -i ./global.css -o ./node_modules/.cache/nativewind/global.css",
12
+ "build:standalone": "expo export -p web --output-dir dist-standalone && node scripts/adjust-standalone-paths.js",
13
+ "build:server": "EXPO_PUBLIC_IS_SERVER_HOSTED=true expo export -p web --output-dir dist-server && node scripts/adjust-server-paths.js",
14
+ "build:server:watch": "npx chokidar '**/*' -i 'dist-standalone/**' -i 'dist-server/**' -i 'node_modules/**' -c 'npm run build:server'",
15
+ "solid-server": "community-solid-server -c ./test-server/server-config.json -f ./data --seed-config ./test-server/solid-css-seed.json",
16
+ "build:ldo": "ldo build --input .shapes --output .ldo",
17
+ "build": "npm run build:standalone && npm run build:server"
18
+ },
19
+ "dependencies": {
20
+ "@inrupt/solid-client-authn-browser": "^2.5.0",
21
+ "@ldo/connected-solid": "^1.0.0-alpha.26",
22
+ "@ldo/ldo": "^1.0.0-alpha.21",
23
+ "@ldo/solid-react": "^1.0.0-alpha.26",
24
+ "@monaco-editor/react": "^4.7.0",
25
+ "@radix-ui/react-dialog": "^1.1.14",
26
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
27
+ "@radix-ui/react-label": "^2.1.7",
28
+ "@radix-ui/react-navigation-menu": "^1.2.13",
29
+ "@radix-ui/react-popover": "^1.1.14",
30
+ "@radix-ui/react-progress": "^1.1.7",
31
+ "@radix-ui/react-radio-group": "^1.3.7",
32
+ "@radix-ui/react-switch": "^1.2.5",
33
+ "@radix-ui/react-tooltip": "^1.2.7",
34
+ "@react-native-async-storage/async-storage": "2.1.2",
35
+ "@react-navigation/native": "^7.1.14",
36
+ "@rn-primitives/avatar": "~1.2.0",
37
+ "@rn-primitives/dialog": "^1.2.0",
38
+ "@rn-primitives/dropdown-menu": "^1.2.0",
39
+ "@rn-primitives/label": "^1.2.0",
40
+ "@rn-primitives/navigation-menu": "^1.2.0",
41
+ "@rn-primitives/popover": "^1.2.0",
42
+ "@rn-primitives/portal": "~1.3.0",
43
+ "@rn-primitives/progress": "~1.2.0",
44
+ "@rn-primitives/radio-group": "^1.2.0",
45
+ "@rn-primitives/separator": "^1.2.0",
46
+ "@rn-primitives/slot": "~1.2.0",
47
+ "@rn-primitives/switch": "^1.2.0",
48
+ "@rn-primitives/tooltip": "~1.2.0",
49
+ "class-variance-authority": "^0.7.0",
50
+ "clsx": "^2.1.0",
51
+ "constate": "^3.3.3",
52
+ "expo": "^53.0.9",
53
+ "expo-linking": "~7.1.5",
54
+ "expo-navigation-bar": "~4.2.4",
55
+ "expo-splash-screen": "~0.30.8",
56
+ "expo-status-bar": "~2.2.3",
57
+ "expo-system-ui": "~5.0.7",
58
+ "lucide-react-native": "^0.511.0",
59
+ "nativewind": "^4.1.23",
60
+ "react": "19.0.0",
61
+ "react-dom": "19.0.0",
62
+ "react-native": "0.79.2",
63
+ "react-native-notifier": "^2.0.0",
64
+ "react-native-reanimated": "~3.17.5",
65
+ "react-native-safe-area-context": "^5.4.0",
66
+ "react-native-screens": "~4.10.0",
67
+ "react-native-svg": "15.11.2",
68
+ "react-native-web": "~0.20.0",
69
+ "tailwind-merge": "^2.2.1",
70
+ "tailwindcss": "3.3.5",
71
+ "tailwindcss-animate": "^1.0.7"
72
+ },
73
+ "devDependencies": {
74
+ "@babel/core": "^7.26.0",
75
+ "@ldo/cli": "^1.0.0-alpha.21",
76
+ "@react-native-community/eslint-config": "^3.2.0",
77
+ "@solid/community-server": "^7.1.7",
78
+ "@types/jsonld": "^1.5.15",
79
+ "@types/react": "~19.0.14",
80
+ "@types/shexj": "^2.1.7",
81
+ "chokidar-cli": "^3.0.0",
82
+ "concurrently": "^9.1.2",
83
+ "eslint-config-prettier": "^10.1.5",
84
+ "eslint-plugin-prettier": "^5.4.1",
85
+ "prettier": "^3.5.3",
86
+ "typescript": "^5.8.3"
87
+ },
88
+ "private": false
89
+ }
@@ -0,0 +1,13 @@
1
+ import { ResourceViewConfig } from '~/components/ResourceView';
2
+ import { Folders } from '~/lib/icons/Folders';
3
+ import { ContainerView } from './ContainerView';
4
+
5
+ export const ContainerConfig: ResourceViewConfig = {
6
+ name: 'container',
7
+ displayName: 'Container',
8
+ displayIcon: Folders,
9
+ view: ContainerView,
10
+ canDisplay: (targetUri, targetResource) => {
11
+ return targetResource.type === 'SolidContainer';
12
+ },
13
+ };
@@ -0,0 +1,148 @@
1
+ import React, { FunctionComponent, useCallback } from 'react';
2
+ import { View, FlatList, TouchableWithoutFeedback } from 'react-native';
3
+ import { Text } from '~/components/ui/text';
4
+ import { Button } from '~/components/ui/button';
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuTrigger,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem,
10
+ } from '~/components/ui/dropdown-menu';
11
+ import { useTargetResource } from '~/components/TargetResourceProvider';
12
+ import { ErrorMessageResourceView } from '~/components/nav/utilityResourceViews/ErrorMessageResourceView';
13
+ import { CircleX } from '~/lib/icons/CircleX';
14
+ import { Folder } from '~/lib/icons/Folder';
15
+ import { Code } from '~/lib/icons/Code';
16
+ import { File } from '~/lib/icons/File';
17
+ import { Trash } from '~/lib/icons/Trash';
18
+ import { Separator } from '~/components/ui/separator';
19
+ import { useDialog } from '~/components/nav/DialogProvider';
20
+ import {
21
+ SolidContainer,
22
+ SolidContainerSlug,
23
+ SolidLeaf,
24
+ } from '@ldo/connected-solid';
25
+ import { Notifier } from 'react-native-notifier';
26
+
27
+ export const ContainerView: FunctionComponent = () => {
28
+ const { targetResource, navigateTo } = useTargetResource();
29
+ const { prompt } = useDialog();
30
+
31
+ const onCreateContainer = useCallback(async () => {
32
+ if (targetResource?.type !== 'SolidContainer') return;
33
+ const givenName = await prompt('Enter Container Name');
34
+ if (!givenName) return;
35
+ const slug = (
36
+ givenName.endsWith('/') ? givenName : `${givenName}/`
37
+ ) as SolidContainerSlug;
38
+ const createResult = await targetResource.createChildIfAbsent(slug);
39
+ if (createResult.isError)
40
+ Notifier.showNotification({ title: createResult.message });
41
+ if (createResult.type === 'containerReadSuccess')
42
+ Notifier.showNotification({ title: `${slug} already exists.` });
43
+ }, [prompt, targetResource]);
44
+
45
+ const onCreateRdf = useCallback(async () => {
46
+ if (targetResource?.type !== 'SolidContainer') return;
47
+ const givenName = await prompt('Enter File Name');
48
+ if (!givenName) return;
49
+ const slug = (
50
+ givenName.endsWith('.ttl') ? givenName : `${givenName}.ttl`
51
+ ) as SolidContainerSlug;
52
+ const createResult = await targetResource.createChildIfAbsent(slug);
53
+ if (createResult.isError)
54
+ Notifier.showNotification({ title: createResult.message });
55
+ if (createResult.type === 'containerReadSuccess')
56
+ Notifier.showNotification({ title: `${slug} already exists.` });
57
+ }, [prompt, targetResource]);
58
+
59
+ const onUpload = useCallback(async () => {
60
+ if (targetResource?.type !== 'SolidContainer') return;
61
+ // Not Implemented
62
+ Notifier.showNotification({ title: 'Not Implemented' });
63
+ }, [targetResource?.type]);
64
+
65
+ const onDelete = useCallback(
66
+ async (item: SolidLeaf | SolidContainer) => {
67
+ if (targetResource?.type !== 'SolidContainer') return;
68
+ const createResult = await item.delete();
69
+ if (createResult.isError)
70
+ Notifier.showNotification({ title: createResult.message });
71
+ },
72
+ [targetResource?.type],
73
+ );
74
+
75
+ if (targetResource?.type !== 'SolidContainer') {
76
+ return (
77
+ <ErrorMessageResourceView
78
+ icon={CircleX}
79
+ message="The target resource is not a container"
80
+ />
81
+ );
82
+ }
83
+
84
+ return (
85
+ <View className="flex-1 flex-row">
86
+ {/* Left Panel */}
87
+ <View className="max-w-[200px] flex-1 p-4">
88
+ <DropdownMenu>
89
+ <DropdownMenuTrigger asChild>
90
+ <Button>
91
+ <Text>Create</Text>
92
+ </Button>
93
+ </DropdownMenuTrigger>
94
+ <DropdownMenuContent>
95
+ <DropdownMenuItem onPress={onCreateContainer}>
96
+ <Text>Container</Text>
97
+ </DropdownMenuItem>
98
+ <DropdownMenuItem onPress={onCreateRdf}>
99
+ <Text>RDF Turtle</Text>
100
+ </DropdownMenuItem>
101
+ <DropdownMenuItem onPress={onUpload}>
102
+ <Text>File Upload</Text>
103
+ </DropdownMenuItem>
104
+ </DropdownMenuContent>
105
+ </DropdownMenu>
106
+ </View>
107
+
108
+ {/* Right Panel */}
109
+ <View className="flex-[3] py-4 pr-4">
110
+ <FlatList
111
+ data={targetResource.children()}
112
+ keyExtractor={(item) => item.uri}
113
+ renderItem={({ item, index }) => {
114
+ const Icon =
115
+ item.type === 'SolidContainer'
116
+ ? Folder
117
+ : item.uri.endsWith('.ttl')
118
+ ? Code
119
+ : File;
120
+ return (
121
+ <>
122
+ {index === 0 && <Separator />}
123
+ <TouchableWithoutFeedback onPress={() => navigateTo(item.uri)}>
124
+ <View className="flex flex-row p-4 hover:bg-secondary rounded-sm cursor-pointer justify-between">
125
+ <Text className="flex flex-row gap-3">
126
+ <Icon />
127
+ {item.uri.replace(targetResource.uri, '')}
128
+ </Text>
129
+ <Button
130
+ variant="ghost"
131
+ className="h-6 p-0"
132
+ onPress={() => onDelete(item)}
133
+ >
134
+ <Text>
135
+ <Trash size={20} />
136
+ </Text>
137
+ </Button>
138
+ </View>
139
+ </TouchableWithoutFeedback>
140
+ <Separator />
141
+ </>
142
+ );
143
+ }}
144
+ />
145
+ </View>
146
+ </View>
147
+ );
148
+ };
@@ -0,0 +1,11 @@
1
+ import { ResourceViewConfig } from '~/components/ResourceView';
2
+ import { Code } from '~/lib/icons/Code';
3
+ import { RawCodeView } from './RawCodeView';
4
+
5
+ export const RawCodeConfig: ResourceViewConfig = {
6
+ name: 'rawCode',
7
+ displayName: 'Raw Code',
8
+ displayIcon: Code,
9
+ view: RawCodeView,
10
+ canDisplay: () => true,
11
+ };
@@ -0,0 +1,37 @@
1
+ import React, { FunctionComponent, useRef } from 'react';
2
+ import { Text } from '~/components/ui/text';
3
+ import Editor, { Monaco, OnMount } from '@monaco-editor/react';
4
+ import { useThemeChange } from '~/components/ThemeProvider';
5
+
6
+ interface RawCodeEditorProps {
7
+ value: string;
8
+ onChange: (value: string | undefined) => void;
9
+ }
10
+
11
+ export const RawCodeEditor: FunctionComponent<RawCodeEditorProps> = ({
12
+ value,
13
+ onChange,
14
+ }) => {
15
+ const monacoRef = useRef<Monaco>(null);
16
+ const { colorScheme } = useThemeChange();
17
+
18
+ function handleEditorWillMount(monaco: Monaco) {
19
+ monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
20
+ }
21
+
22
+ const handleEditorDidMount: OnMount = (editor, monaco) => {
23
+ monacoRef.current = monaco;
24
+ };
25
+
26
+ return (
27
+ <Editor
28
+ className="flex-1"
29
+ defaultLanguage="turtle"
30
+ theme={colorScheme === 'light' ? 'light' : 'hc-black'}
31
+ value={value}
32
+ onChange={onChange}
33
+ beforeMount={handleEditorWillMount}
34
+ onMount={handleEditorDidMount}
35
+ />
36
+ );
37
+ };
@@ -0,0 +1,67 @@
1
+ import { useSolidAuth } from '@ldo/solid-react';
2
+ import React, {
3
+ FunctionComponent,
4
+ useCallback,
5
+ useEffect,
6
+ useState,
7
+ } from 'react';
8
+ import { useTargetResource } from '~/components/TargetResourceProvider';
9
+ import { RawCodeEditor } from './RawCodeEditor';
10
+ import { View } from 'react-native';
11
+ import { Button } from '~/components/ui/button';
12
+ import { Text } from '~/components/ui/text';
13
+ import { Notifier } from 'react-native-notifier';
14
+
15
+ export const RawCodeView: FunctionComponent = () => {
16
+ const { targetUri } = useTargetResource();
17
+ const { fetch } = useSolidAuth();
18
+ const [content, setContent] = useState<string>('');
19
+
20
+ // Independently fetch the target resource, so we have the raw turtle
21
+ const fetchContent = useCallback(async () => {
22
+ if (!targetUri) return;
23
+ const response = await fetch(targetUri);
24
+ if (response.status !== 200) {
25
+ Notifier.showNotification({
26
+ title: `Could not fetch document. Recieved ${response.status}`,
27
+ });
28
+ }
29
+ setContent(await response.text());
30
+ }, [fetch, targetUri]);
31
+
32
+ const submitChanges = useCallback(async () => {
33
+ if (!targetUri) return;
34
+ const response = await fetch(targetUri, {
35
+ method: 'put',
36
+ body: content,
37
+ });
38
+ if (response.status !== 205) {
39
+ Notifier.showNotification({
40
+ title: `Could save document. Recieved ${response.status}`,
41
+ });
42
+ }
43
+ Notifier.showNotification({
44
+ title: `Document Saved`,
45
+ });
46
+ await fetchContent();
47
+ }, [content, fetch, fetchContent, targetUri]);
48
+
49
+ useEffect(() => {
50
+ fetchContent();
51
+ }, [fetchContent]);
52
+
53
+ return (
54
+ <View className="flex-1 relative">
55
+ <RawCodeEditor
56
+ value={content}
57
+ onChange={(value) => setContent(value ?? '')}
58
+ />
59
+ <Button
60
+ className="absolute bottom-2 right-2 z-10"
61
+ onPress={submitChanges}
62
+ >
63
+ <Text>Save Changes</Text>
64
+ </Button>
65
+ </View>
66
+ );
67
+ };
@@ -0,0 +1,37 @@
1
+ // scripts/adjust-server-paths.js
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const indexHtmlPath = path.join(__dirname, '../dist-server/index.html');
6
+
7
+ fs.readFile(indexHtmlPath, 'utf8', (err, data) => {
8
+ if (err) {
9
+ console.error('Error reading index.html:', err);
10
+ return;
11
+ }
12
+
13
+ // Regex to prefix all root-relative href and src paths,
14
+ // unless they already contain '/.ui-static/'
15
+ let modifiedData = data.replace(
16
+ /(href|src)=["'](\/(?!\.ui-static\/)\S*?)["']/g,
17
+ (match, attr, urlPath) => {
18
+ return `${attr}="/.ui-static${urlPath}"`;
19
+ },
20
+ );
21
+
22
+ // Modify the hydration flag for server-hosted build to false
23
+ modifiedData = modifiedData.replace(
24
+ /globalThis\.__EXPO_ROUTER_HYDRATE__=true;/,
25
+ 'globalThis.__EXPO_ROUTER_HYDRATE__=false;',
26
+ );
27
+
28
+ fs.writeFile(indexHtmlPath, modifiedData, 'utf8', (err2) => {
29
+ if (err2) {
30
+ console.error('Error writing index.html:', err2);
31
+ return;
32
+ }
33
+ console.log(
34
+ 'Successfully adjusted paths and hydration flag in dist-server/index.html',
35
+ );
36
+ });
37
+ });
@@ -0,0 +1,28 @@
1
+ // scripts/adjust-server-paths.js
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const indexHtmlPath = path.join(__dirname, '../dist-standalone/index.html');
6
+
7
+ fs.readFile(indexHtmlPath, 'utf8', (err, data) => {
8
+ if (err) {
9
+ console.error('Error reading index.html:', err);
10
+ return;
11
+ }
12
+
13
+ // Modify the hydration flag for server-hosted build to false
14
+ let modifiedData = data.replace(
15
+ /globalThis\.__EXPO_ROUTER_HYDRATE__=true;/,
16
+ 'globalThis.__EXPO_ROUTER_HYDRATE__=false;',
17
+ );
18
+
19
+ fs.writeFile(indexHtmlPath, modifiedData, 'utf8', (err2) => {
20
+ if (err2) {
21
+ console.error('Error writing index.html:', err2);
22
+ return;
23
+ }
24
+ console.log(
25
+ 'Successfully adjusted hydration flag in dist-standalone/index.html',
26
+ );
27
+ });
28
+ });
@@ -0,0 +1,69 @@
1
+ const { hairlineWidth } = require('nativewind/theme');
2
+
3
+ /** @type {import('tailwindcss').Config} */
4
+ module.exports = {
5
+ darkMode: 'class',
6
+ content: [
7
+ './app/**/*.{ts,tsx}',
8
+ './components/**/*.{ts,tsx}',
9
+ './resourceViews/**/*.{ts,tsx}',
10
+ ],
11
+ presets: [require('nativewind/preset')],
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ border: 'hsl(var(--border))',
16
+ input: 'hsl(var(--input))',
17
+ ring: 'hsl(var(--ring))',
18
+ background: 'hsl(var(--background))',
19
+ foreground: 'hsl(var(--foreground))',
20
+ primary: {
21
+ DEFAULT: 'hsl(var(--primary))',
22
+ foreground: 'hsl(var(--primary-foreground))',
23
+ },
24
+ secondary: {
25
+ DEFAULT: 'hsl(var(--secondary))',
26
+ foreground: 'hsl(var(--secondary-foreground))',
27
+ },
28
+ destructive: {
29
+ DEFAULT: 'hsl(var(--destructive))',
30
+ foreground: 'hsl(var(--destructive-foreground))',
31
+ },
32
+ muted: {
33
+ DEFAULT: 'hsl(var(--muted))',
34
+ foreground: 'hsl(var(--muted-foreground))',
35
+ },
36
+ accent: {
37
+ DEFAULT: 'hsl(var(--accent))',
38
+ foreground: 'hsl(var(--accent-foreground))',
39
+ },
40
+ popover: {
41
+ DEFAULT: 'hsl(var(--popover))',
42
+ foreground: 'hsl(var(--popover-foreground))',
43
+ },
44
+ card: {
45
+ DEFAULT: 'hsl(var(--card))',
46
+ foreground: 'hsl(var(--card-foreground))',
47
+ },
48
+ },
49
+ borderWidth: {
50
+ hairline: hairlineWidth(),
51
+ },
52
+ keyframes: {
53
+ 'accordion-down': {
54
+ from: { height: '0' },
55
+ to: { height: 'var(--radix-accordion-content-height)' },
56
+ },
57
+ 'accordion-up': {
58
+ from: { height: 'var(--radix-accordion-content-height)' },
59
+ to: { height: '0' },
60
+ },
61
+ },
62
+ animation: {
63
+ 'accordion-down': 'accordion-down 0.2s ease-out',
64
+ 'accordion-up': 'accordion-up 0.2s ease-out',
65
+ },
66
+ },
67
+ },
68
+ plugins: [require('tailwindcss-animate')],
69
+ };
@@ -0,0 +1,75 @@
1
+ {
2
+ "@context": [
3
+ "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld"
4
+ ],
5
+ "import": [
6
+ "css:config/app/init/default.json",
7
+ "css:config/app/main/default.json",
8
+ "css:config/app/variables/default.json",
9
+ "css:config/http/handler/default.json",
10
+ "css:config/http/middleware/default.json",
11
+ "css:config/http/notifications/all.json",
12
+ "css:config/http/server-factory/http.json",
13
+ "css:config/http/static/default.json",
14
+ "css:config/identity/access/public.json",
15
+ "css:config/identity/email/default.json",
16
+ "css:config/identity/handler/default.json",
17
+ "css:config/identity/oidc/default.json",
18
+ "css:config/identity/ownership/token.json",
19
+ "css:config/identity/pod/static.json",
20
+ "css:config/ldp/authentication/dpop-bearer.json",
21
+ "css:config/ldp/authorization/webacl.json",
22
+ "css:config/ldp/handler/default.json",
23
+ "css:config/ldp/metadata-parser/default.json",
24
+ "css:config/ldp/metadata-writer/default.json",
25
+ "css:config/ldp/modes/default.json",
26
+ "css:config/storage/backend/file.json",
27
+ "css:config/storage/key-value/resource-store.json",
28
+ "css:config/storage/location/pod.json",
29
+ "css:config/storage/middleware/default.json",
30
+ "css:config/util/auxiliary/acl.json",
31
+ "css:config/util/identifiers/suffix.json",
32
+ "css:config/util/logging/winston.json",
33
+ "css:config/util/representation-conversion/default.json",
34
+ "css:config/util/resource-locker/file.json",
35
+ "css:config/util/variables/default.json"
36
+ ],
37
+ "@graph": [
38
+ {
39
+ "comment": "A Solid server that stores its resources on disk and uses WAC for authorization."
40
+ },
41
+ {
42
+ "comment": "Serve Linked-Data-Browser as default representation",
43
+ "@id": "urn:solid-server:default:DefaultUiConverter",
44
+ "@type": "ConstantConverter",
45
+ "contentType": "text/html",
46
+ "filePath": "./dist-server/index.html",
47
+ "options_container": true,
48
+ "options_document": true,
49
+ "options_minQuality": 1
50
+ },
51
+ {
52
+ "@type": "Override",
53
+ "overrideInstance": {
54
+ "@type": "StaticAssetEntry",
55
+ "@id": "urn:solid-server:default:RootStaticAsset"
56
+ },
57
+ "overrideParameters": {
58
+ "@type": "StaticAssetEntry",
59
+ "filePath": "./dist-server/index.html"
60
+ }
61
+ },
62
+ {
63
+ "comment": "Serve Linked-Data-Browser static files.",
64
+ "@id": "urn:solid-server:default:StaticAssetHandler",
65
+ "@type": "StaticAssetHandler",
66
+ "assets": [
67
+ {
68
+ "@type": "StaticAssetEntry",
69
+ "relativeUrl": "/.ui-static/",
70
+ "filePath": "./dist-server/"
71
+ }
72
+ ]
73
+ }
74
+ ]
75
+ }
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "email": "hello@example.com",
4
+ "password": "abc123",
5
+ "pods": [
6
+ {
7
+ "name": "example"
8
+ }
9
+ ]
10
+ }
11
+ ]
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "baseUrl": ".",
6
+ "paths": {
7
+ "~/*": [
8
+ "*"
9
+ ]
10
+ }
11
+ },
12
+ "include": [
13
+ "**/*.ts",
14
+ "**/*.tsx",
15
+ ".expo/types/**/*.ts",
16
+ "expo-env.d.ts",
17
+ "nativewind-env.d.ts"
18
+ ]
19
+ }