@vertebr/react 0.1.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.
@@ -0,0 +1,103 @@
1
+ export type FieldType = "string" | "number" | "boolean" | "datetime" | "richtext" | "enum" | "enum[]" | "file[]";
2
+ export type FieldSchema = {
3
+ type: FieldType;
4
+ label?: string;
5
+ required?: boolean;
6
+ readOnly?: boolean;
7
+ unique?: boolean;
8
+ min?: number;
9
+ max?: number;
10
+ default?: unknown;
11
+ options?: string[];
12
+ };
13
+ export type EnvironmentAuthPublic = {
14
+ required: boolean;
15
+ claimKey?: string;
16
+ roles?: string[];
17
+ client?: {
18
+ provider: "firebase";
19
+ config: {
20
+ apiKey: string;
21
+ authDomain: string;
22
+ projectId: string;
23
+ appId: string;
24
+ messagingSenderId?: string;
25
+ };
26
+ methods?: Array<"email" | "google">;
27
+ };
28
+ };
29
+ export type AdminEnvironment = {
30
+ id: string;
31
+ label: string;
32
+ tone?: "neutral" | "warn" | "danger";
33
+ auth?: EnvironmentAuthPublic;
34
+ };
35
+ export type CatalogResource = {
36
+ id: string;
37
+ label: string;
38
+ schema: Record<string, FieldSchema>;
39
+ permissions: {
40
+ create?: boolean;
41
+ update?: boolean;
42
+ delete?: boolean;
43
+ };
44
+ };
45
+ export type CatalogConfig = {
46
+ id: string;
47
+ label: string;
48
+ schema: Record<string, FieldSchema>;
49
+ };
50
+ export type BootstrapResponse = {
51
+ ok: boolean;
52
+ brand: string;
53
+ defaultEnvironment: string;
54
+ environments: AdminEnvironment[];
55
+ };
56
+ export type CatalogResponse = {
57
+ ok: boolean;
58
+ brand: string;
59
+ environment: string;
60
+ environments: AdminEnvironment[];
61
+ defaultEnvironment: string;
62
+ resources: CatalogResource[];
63
+ configs: CatalogConfig[];
64
+ metrics?: {
65
+ id: string;
66
+ label: string;
67
+ } | null;
68
+ };
69
+ export type ResourceActionMeta = {
70
+ label: string;
71
+ input?: Record<string, FieldType>;
72
+ };
73
+ export type ResourceListResponse = {
74
+ id: string;
75
+ label: string;
76
+ schema: Record<string, FieldSchema>;
77
+ environment?: string;
78
+ permissions: CatalogResource["permissions"];
79
+ actions?: Record<string, ResourceActionMeta>;
80
+ items: Record<string, unknown>[];
81
+ };
82
+ export type MetricCard = {
83
+ id: string;
84
+ label: string;
85
+ value: string | number;
86
+ hint?: string;
87
+ tone?: "neutral" | "ok" | "warn" | "danger";
88
+ };
89
+ export type MetricsResponse = {
90
+ ok: boolean;
91
+ id: string;
92
+ label: string;
93
+ environment?: string;
94
+ metrics: MetricCard[];
95
+ };
96
+ export type ConfigResponse = {
97
+ id: string;
98
+ label: string;
99
+ schema: Record<string, FieldSchema>;
100
+ environment?: string;
101
+ value: Record<string, unknown>;
102
+ };
103
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { type ReactNode } from "react";
2
+ export type VertebrControlsMap = Record<string, Record<string, unknown>>;
3
+ type ControlsContextValue = {
4
+ environment: string;
5
+ controls: VertebrControlsMap;
6
+ loading: boolean;
7
+ error: Error | null;
8
+ refresh: () => Promise<void>;
9
+ };
10
+ export type VertebrControlsProviderProps = {
11
+ /** Vertebr API base, e.g. `/admin/api`. */
12
+ apiBase?: string;
13
+ /** Active app environment (qual / production). */
14
+ environment: string;
15
+ children: ReactNode;
16
+ };
17
+ /**
18
+ * Loads all public Vertebr controls for the storefront once and shares them.
19
+ */
20
+ export declare function VertebrControlsProvider({ apiBase, environment, children, }: VertebrControlsProviderProps): import("react").JSX.Element;
21
+ /**
22
+ * Read a public Vertebr control by id.
23
+ * Falls back to `fallback` while loading or if the control is missing.
24
+ */
25
+ export declare function useVertebrConfig<T extends Record<string, unknown>>(id: string, fallback: T): {
26
+ data: T;
27
+ loading: boolean;
28
+ error: Error | null;
29
+ refresh: () => Promise<void>;
30
+ };
31
+ /** Access the full public controls map (for gates like comingSoon). */
32
+ export declare function useVertebrControls(): ControlsContextValue;
33
+ export {};
34
+ //# sourceMappingURL=useVertebrControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVertebrControls.d.ts","sourceRoot":"","sources":["../src/useVertebrControls.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEzE,KAAK,oBAAoB,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAIF,MAAM,MAAM,4BAA4B,GAAG;IACzC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AA2BF;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,OAAsB,EACtB,WAAW,EACX,QAAQ,GACT,EAAE,4BAA4B,+BA8B9B;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,GACV;IACD,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAMA;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,IAAI,oBAAoB,CAEzD"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
3
+ import { VERTEBR_ENV_HEADER } from "./client";
4
+ const ControlsContext = createContext(null);
5
+ async function fetchPublicControls(apiBase, environment) {
6
+ const base = apiBase.replace(/\/$/, "");
7
+ const response = await fetch(`${base}/public/controls`, {
8
+ headers: {
9
+ Accept: "application/json",
10
+ [VERTEBR_ENV_HEADER]: environment,
11
+ },
12
+ });
13
+ if (!response.ok) {
14
+ const text = await response.text();
15
+ throw new Error(text || `Failed to load controls (${response.status})`);
16
+ }
17
+ const body = (await response.json());
18
+ return body.configs ?? {};
19
+ }
20
+ /**
21
+ * Loads all public Vertebr controls for the storefront once and shares them.
22
+ */
23
+ export function VertebrControlsProvider({ apiBase = "/admin/api", environment, children, }) {
24
+ const [controls, setControls] = useState({});
25
+ const [loading, setLoading] = useState(true);
26
+ const [error, setError] = useState(null);
27
+ const refresh = useCallback(async () => {
28
+ setLoading(true);
29
+ setError(null);
30
+ try {
31
+ const next = await fetchPublicControls(apiBase, environment);
32
+ setControls(next);
33
+ }
34
+ catch (err) {
35
+ setError(err instanceof Error ? err : new Error("Failed to load controls"));
36
+ }
37
+ finally {
38
+ setLoading(false);
39
+ }
40
+ }, [apiBase, environment]);
41
+ useEffect(() => {
42
+ void refresh();
43
+ }, [refresh]);
44
+ const value = useMemo(() => ({ environment, controls, loading, error, refresh }), [environment, controls, loading, error, refresh]);
45
+ return (_jsx(ControlsContext.Provider, { value: value, children: children }));
46
+ }
47
+ function useControlsContext() {
48
+ const ctx = useContext(ControlsContext);
49
+ if (!ctx) {
50
+ throw new Error("useVertebrConfig must be used within VertebrControlsProvider");
51
+ }
52
+ return ctx;
53
+ }
54
+ /**
55
+ * Read a public Vertebr control by id.
56
+ * Falls back to `fallback` while loading or if the control is missing.
57
+ */
58
+ export function useVertebrConfig(id, fallback) {
59
+ const { controls, loading, error, refresh } = useControlsContext();
60
+ const raw = controls[id];
61
+ const data = { ...fallback, ...(raw ?? {}) };
62
+ return { data, loading, error, refresh };
63
+ }
64
+ /** Access the full public controls map (for gates like comingSoon). */
65
+ export function useVertebrControls() {
66
+ return useControlsContext();
67
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@vertebr/react",
3
+ "version": "0.1.0",
4
+ "description": "Vertebr admin dashboard UI",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./styles.css": "./dist/styles.css"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc -p tsconfig.json && cp src/styles.css dist/styles.css",
20
+ "typecheck": "tsc -p tsconfig.json --noEmit",
21
+ "prepublishOnly": "npm run typecheck && npm run build"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/yaboijams/vertebr.git",
26
+ "directory": "packages/react"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public",
30
+ "registry": "https://registry.npmjs.org"
31
+ },
32
+ "peerDependencies": {
33
+ "react": "^18.0.0 || ^19.0.0",
34
+ "react-dom": "^18.0.0 || ^19.0.0"
35
+ },
36
+ "dependencies": {
37
+ "@hookform/resolvers": "^5.2.1",
38
+ "@radix-ui/react-label": "^2.1.7",
39
+ "@radix-ui/react-select": "^2.3.7",
40
+ "@radix-ui/react-separator": "^1.1.7",
41
+ "@radix-ui/react-switch": "^1.2.5",
42
+ "@tanstack/react-table": "^8.21.3",
43
+ "react-hook-form": "^7.62.0",
44
+ "zod": "^3.25.76"
45
+ },
46
+ "devDependencies": {
47
+ "@types/react": "^19.2.17",
48
+ "@types/react-dom": "^19.2.3",
49
+ "react": "^19.2.8",
50
+ "react-dom": "^19.2.8",
51
+ "typescript": "^5.9.2"
52
+ },
53
+ "license": "MIT"
54
+ }