@hcgstudio/ogma 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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +155 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/defineOgmaReview.d.ts +3 -0
  8. package/dist/defineOgmaReview.d.ts.map +1 -0
  9. package/dist/defineOgmaReview.js +4 -0
  10. package/dist/defineOgmaReview.js.map +1 -0
  11. package/dist/index.d.ts +5 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +4 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/node/project.d.ts +18 -0
  16. package/dist/node/project.d.ts.map +1 -0
  17. package/dist/node/project.js +104 -0
  18. package/dist/node/project.js.map +1 -0
  19. package/dist/node/server.d.ts +21 -0
  20. package/dist/node/server.d.ts.map +1 -0
  21. package/dist/node/server.js +476 -0
  22. package/dist/node/server.js.map +1 -0
  23. package/dist/node/templates.d.ts +5 -0
  24. package/dist/node/templates.d.ts.map +1 -0
  25. package/dist/node/templates.js +145 -0
  26. package/dist/node/templates.js.map +1 -0
  27. package/dist/types.d.ts +100 -0
  28. package/dist/types.d.ts.map +1 -0
  29. package/dist/types.js +2 -0
  30. package/dist/types.js.map +1 -0
  31. package/dist/viewer/OgmaReviewApp.d.ts +7 -0
  32. package/dist/viewer/OgmaReviewApp.d.ts.map +1 -0
  33. package/dist/viewer/OgmaReviewApp.js +387 -0
  34. package/dist/viewer/OgmaReviewApp.js.map +1 -0
  35. package/dist/viewer/client.d.ts +2 -0
  36. package/dist/viewer/client.d.ts.map +1 -0
  37. package/dist/viewer/client.js +13 -0
  38. package/dist/viewer/client.js.map +1 -0
  39. package/dist/viewer/defaultReview.d.ts +4 -0
  40. package/dist/viewer/defaultReview.d.ts.map +1 -0
  41. package/dist/viewer/defaultReview.js +55 -0
  42. package/dist/viewer/defaultReview.js.map +1 -0
  43. package/dist/viewer/normalizeReviewModule.d.ts +3 -0
  44. package/dist/viewer/normalizeReviewModule.d.ts.map +1 -0
  45. package/dist/viewer/normalizeReviewModule.js +58 -0
  46. package/dist/viewer/normalizeReviewModule.js.map +1 -0
  47. package/package.json +47 -0
  48. package/src/cli.ts +194 -0
  49. package/src/defineOgmaReview.ts +5 -0
  50. package/src/index.ts +17 -0
  51. package/src/node/project.ts +143 -0
  52. package/src/node/server.ts +598 -0
  53. package/src/node/templates.ts +148 -0
  54. package/src/types.ts +111 -0
  55. package/src/viewer/OgmaReviewApp.tsx +1099 -0
  56. package/src/viewer/client.tsx +18 -0
  57. package/src/viewer/defaultReview.tsx +168 -0
  58. package/src/viewer/normalizeReviewModule.ts +87 -0
  59. package/src/viewer/styles.css +1140 -0
  60. package/src/viewer/virtual.d.ts +11 -0
@@ -0,0 +1,18 @@
1
+ import { StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { runtimeConfig } from 'virtual:ogma-config';
4
+ import { review } from 'virtual:ogma-design';
5
+ import { OgmaReviewApp } from './OgmaReviewApp.js';
6
+ import './styles.css';
7
+
8
+ const root = document.getElementById('ogma-root');
9
+
10
+ if (!root) {
11
+ throw new Error('Ogma could not find #ogma-root.');
12
+ }
13
+
14
+ createRoot(root).render(
15
+ <StrictMode>
16
+ <OgmaReviewApp config={runtimeConfig} review={review} />
17
+ </StrictMode>
18
+ );
@@ -0,0 +1,168 @@
1
+ import type { OgmaReviewDefinition, OgmaPrototypeScreenProps } from '../types.js';
2
+
3
+ function DashboardScreen() {
4
+ return (
5
+ <div className="ogma-demo-screen">
6
+ <aside className="ogma-demo-sidebar">
7
+ <div className="ogma-demo-brand">O</div>
8
+ <span className="ogma-demo-nav is-active">Overview</span>
9
+ <span className="ogma-demo-nav">Signals</span>
10
+ <span className="ogma-demo-nav">Queue</span>
11
+ <span className="ogma-demo-nav">Settings</span>
12
+ </aside>
13
+ <main className="ogma-demo-content">
14
+ <div className="ogma-demo-header">
15
+ <div>
16
+ <p>Dashboard</p>
17
+ <h2>Atlas Brief</h2>
18
+ </div>
19
+ <button type="button">Review ready</button>
20
+ </div>
21
+ <div className="ogma-demo-grid">
22
+ <section className="ogma-demo-card is-wide">
23
+ <div className="ogma-demo-card-title" />
24
+ <div className="ogma-demo-chart">
25
+ {[42, 68, 53, 81, 61, 75, 88].map((value) => (
26
+ <span key={value} style={{ height: `${value}%` }} />
27
+ ))}
28
+ </div>
29
+ </section>
30
+ <section className="ogma-demo-card is-accent">
31
+ <strong>91%</strong>
32
+ <p>Review confidence</p>
33
+ </section>
34
+ <section className="ogma-demo-card">
35
+ <div className="ogma-demo-list-row" />
36
+ <div className="ogma-demo-list-row is-medium" />
37
+ <div className="ogma-demo-list-row is-short" />
38
+ </section>
39
+ <section className="ogma-demo-card is-action">
40
+ <strong>2</strong>
41
+ <p>Copy edits before approval</p>
42
+ </section>
43
+ </div>
44
+ </main>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ function DesignSpecScreen() {
50
+ return (
51
+ <div className="ogma-spec-screen">
52
+ <header>
53
+ <p>Design spec</p>
54
+ <h2>Decision System</h2>
55
+ </header>
56
+ <div className="ogma-spec-grid">
57
+ {['Information density', 'Review confidence', 'Agent handoff', 'Mobile parity'].map(
58
+ (item, index) => (
59
+ <section key={item}>
60
+ <span>{`0${index + 1}`}</span>
61
+ <h3>{item}</h3>
62
+ <p>Prototype state prepared for pinned reviewer feedback and agent follow-up.</p>
63
+ </section>
64
+ )
65
+ )}
66
+ </div>
67
+ </div>
68
+ );
69
+ }
70
+
71
+ function CheckoutFlowScreen() {
72
+ return (
73
+ <div className="ogma-flow-screen">
74
+ <header>
75
+ <p>Checkout flow</p>
76
+ <h2>Approve Plan</h2>
77
+ </header>
78
+ <div className="ogma-flow-columns">
79
+ {['Cart', 'Review', 'Confirm'].map((step, index) => (
80
+ <section key={step}>
81
+ <span>{index + 1}</span>
82
+ <h3>{step}</h3>
83
+ <div className="ogma-flow-line" />
84
+ <button type="button">{index === 2 ? 'Approve' : 'Continue'}</button>
85
+ </section>
86
+ ))}
87
+ </div>
88
+ </div>
89
+ );
90
+ }
91
+
92
+ function MobileNavigationScreen() {
93
+ return (
94
+ <div className="ogma-mobile-screen">
95
+ <div className="ogma-phone">
96
+ <header>
97
+ <span>Ogma</span>
98
+ <button type="button">New</button>
99
+ </header>
100
+ <main>
101
+ <section>
102
+ <p>Mobile nav</p>
103
+ <h2>Design queue</h2>
104
+ </section>
105
+ <div className="ogma-phone-list">
106
+ <span />
107
+ <span />
108
+ <span />
109
+ </div>
110
+ </main>
111
+ <nav>
112
+ <span className="is-active" />
113
+ <span />
114
+ <span />
115
+ </nav>
116
+ </div>
117
+ </div>
118
+ );
119
+ }
120
+
121
+ export function createDefaultOgmaReview(): OgmaReviewDefinition {
122
+ return {
123
+ title: 'Ogma starter review',
124
+ description: 'A local starter review used until an agent writes project-specific JSX screens.',
125
+ notes:
126
+ 'Use this starter review to confirm Ogma is running, then replace it with product-specific JSX screens and product notes in designs/ogma.',
127
+ metadata: {
128
+ source: 'ogma-default',
129
+ updatedAt: new Date().toISOString()
130
+ },
131
+ screens: [
132
+ {
133
+ id: 'dashboard',
134
+ title: 'Dashboard',
135
+ description: 'Main review workspace for desktop inspection.',
136
+ component: DashboardScreen
137
+ },
138
+ {
139
+ id: 'design-spec',
140
+ title: 'Design spec',
141
+ description: 'Product decisions and design rationale.',
142
+ component: DesignSpecScreen
143
+ },
144
+ {
145
+ id: 'checkout-flow',
146
+ title: 'Checkout flow',
147
+ description: 'Interaction state for a step-based product path.',
148
+ component: CheckoutFlowScreen
149
+ },
150
+ {
151
+ id: 'mobile-navigation',
152
+ title: 'Mobile nav',
153
+ description: 'Compact viewport state for mobile review.',
154
+ component: MobileNavigationScreen,
155
+ width: 390
156
+ }
157
+ ]
158
+ };
159
+ }
160
+
161
+ export function MissingScreen({ screen }: OgmaPrototypeScreenProps) {
162
+ return (
163
+ <div className="ogma-empty-screen">
164
+ <h2>{screen.title}</h2>
165
+ <p>This screen is missing a React component export.</p>
166
+ </div>
167
+ );
168
+ }
@@ -0,0 +1,87 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { OgmaPrototypeScreen, OgmaPrototypeScreenProps, OgmaReviewDefinition } from '../types.js';
3
+ import { createDefaultOgmaReview, MissingScreen } from './defaultReview.js';
4
+
5
+ interface ReviewModuleShape {
6
+ default?: unknown;
7
+ review?: unknown;
8
+ ogmaReview?: unknown;
9
+ screens?: unknown;
10
+ title?: unknown;
11
+ description?: unknown;
12
+ notes?: unknown;
13
+ metadata?: unknown;
14
+ }
15
+
16
+ function slugify(value: string, fallback: string) {
17
+ const slug = value
18
+ .trim()
19
+ .toLowerCase()
20
+ .replace(/[^a-z0-9]+/g, '-')
21
+ .replace(/^-+|-+$/g, '');
22
+
23
+ return slug || fallback;
24
+ }
25
+
26
+ function isObject(value: unknown): value is Record<string, unknown> {
27
+ return typeof value === 'object' && value !== null;
28
+ }
29
+
30
+ function normalizeScreen(value: unknown, index: number): OgmaPrototypeScreen | null {
31
+ if (!isObject(value)) {
32
+ return null;
33
+ }
34
+
35
+ const title = typeof value.title === 'string' ? value.title : `Screen ${index + 1}`;
36
+ const component = (
37
+ typeof value.component === 'function'
38
+ ? (value.component as ComponentType)
39
+ : typeof value.Component === 'function'
40
+ ? (value.Component as ComponentType)
41
+ : MissingScreen
42
+ ) as ComponentType<OgmaPrototypeScreenProps>;
43
+
44
+ return {
45
+ id: typeof value.id === 'string' ? slugify(value.id, `screen-${index + 1}`) : slugify(title, `screen-${index + 1}`),
46
+ title,
47
+ description: typeof value.description === 'string' ? value.description : undefined,
48
+ width: typeof value.width === 'number' ? value.width : undefined,
49
+ height: typeof value.height === 'number' ? value.height : undefined,
50
+ component
51
+ };
52
+ }
53
+
54
+ function pickReviewCandidate(moduleValue: ReviewModuleShape) {
55
+ return moduleValue.default ?? moduleValue.review ?? moduleValue.ogmaReview ?? moduleValue;
56
+ }
57
+
58
+ export function normalizeReviewModule(moduleValue: unknown, productNotes = ''): OgmaReviewDefinition {
59
+ const fallback = createDefaultOgmaReview();
60
+
61
+ if (!isObject(moduleValue)) {
62
+ return { ...fallback, notes: productNotes || fallback.notes };
63
+ }
64
+
65
+ const candidate = pickReviewCandidate(moduleValue);
66
+
67
+ if (!isObject(candidate) || !Array.isArray(candidate.screens)) {
68
+ return { ...fallback, notes: productNotes || fallback.notes };
69
+ }
70
+
71
+ const screens = candidate.screens
72
+ .map((screen, index) => normalizeScreen(screen, index))
73
+ .filter((screen): screen is OgmaPrototypeScreen => screen !== null);
74
+
75
+ if (screens.length === 0) {
76
+ return { ...fallback, notes: productNotes || fallback.notes };
77
+ }
78
+
79
+ return {
80
+ title: typeof candidate.title === 'string' ? candidate.title : fallback.title,
81
+ description:
82
+ typeof candidate.description === 'string' ? candidate.description : fallback.description,
83
+ screens,
84
+ notes: productNotes || (typeof candidate.notes === 'string' ? candidate.notes : fallback.notes),
85
+ metadata: isObject(candidate.metadata) ? candidate.metadata : fallback.metadata
86
+ };
87
+ }