@contractspec/lib.surface-runtime 0.2.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 (232) hide show
  1. package/README.md +164 -0
  2. package/dist/adapters/ai-sdk-stub.d.ts +5 -0
  3. package/dist/adapters/ai-sdk-stub.js +13 -0
  4. package/dist/adapters/blocknote-stub.d.ts +6 -0
  5. package/dist/adapters/blocknote-stub.js +31 -0
  6. package/dist/adapters/dnd-kit-adapter.d.ts +13 -0
  7. package/dist/adapters/dnd-kit-adapter.js +44 -0
  8. package/dist/adapters/dnd-kit-stub.d.ts +6 -0
  9. package/dist/adapters/dnd-kit-stub.js +8 -0
  10. package/dist/adapters/floating-ui-stub.d.ts +6 -0
  11. package/dist/adapters/floating-ui-stub.js +19 -0
  12. package/dist/adapters/index.d.ts +11 -0
  13. package/dist/adapters/index.js +176 -0
  14. package/dist/adapters/interfaces.d.ts +75 -0
  15. package/dist/adapters/interfaces.js +1 -0
  16. package/dist/adapters/motion-stub.d.ts +7 -0
  17. package/dist/adapters/motion-stub.js +27 -0
  18. package/dist/adapters/motion-stub.test.d.ts +1 -0
  19. package/dist/adapters/resizable-panels-stub.d.ts +6 -0
  20. package/dist/adapters/resizable-panels-stub.js +46 -0
  21. package/dist/adapters/resizable-panels-stub.test.d.ts +1 -0
  22. package/dist/browser/adapters/ai-sdk-stub.js +12 -0
  23. package/dist/browser/adapters/blocknote-stub.js +30 -0
  24. package/dist/browser/adapters/dnd-kit-adapter.js +43 -0
  25. package/dist/browser/adapters/dnd-kit-stub.js +7 -0
  26. package/dist/browser/adapters/floating-ui-stub.js +18 -0
  27. package/dist/browser/adapters/index.js +175 -0
  28. package/dist/browser/adapters/interfaces.js +0 -0
  29. package/dist/browser/adapters/motion-stub.js +26 -0
  30. package/dist/browser/adapters/resizable-panels-stub.js +45 -0
  31. package/dist/browser/evals/golden-context.js +0 -0
  32. package/dist/browser/evals/golden-harness.js +848 -0
  33. package/dist/browser/examples/pm-workbench.bundle.js +476 -0
  34. package/dist/browser/i18n/catalogs/en.js +71 -0
  35. package/dist/browser/i18n/catalogs/es.js +32 -0
  36. package/dist/browser/i18n/catalogs/fr.js +32 -0
  37. package/dist/browser/i18n/catalogs/index.js +133 -0
  38. package/dist/browser/i18n/index.js +173 -0
  39. package/dist/browser/i18n/keys.js +19 -0
  40. package/dist/browser/i18n/messages.js +143 -0
  41. package/dist/browser/index.js +2466 -0
  42. package/dist/browser/react/BundleProvider.js +47 -0
  43. package/dist/browser/react/BundleRenderer.js +726 -0
  44. package/dist/browser/react/OverlayConflictResolver.js +255 -0
  45. package/dist/browser/react/PatchProposalCard.js +255 -0
  46. package/dist/browser/react/RegionRenderer.js +128 -0
  47. package/dist/browser/react/SlotRenderer.js +118 -0
  48. package/dist/browser/react/WidgetPalette.js +59 -0
  49. package/dist/browser/react/index.js +792 -0
  50. package/dist/browser/runtime/apply-surface-patch.js +322 -0
  51. package/dist/browser/runtime/audit-events.js +137 -0
  52. package/dist/browser/runtime/build-context.js +55 -0
  53. package/dist/browser/runtime/extension-registry.js +58 -0
  54. package/dist/browser/runtime/field-renderer-registry.js +145 -0
  55. package/dist/browser/runtime/index.js +1496 -0
  56. package/dist/browser/runtime/overlay-alignment.js +83 -0
  57. package/dist/browser/runtime/overlay-signer.js +15 -0
  58. package/dist/browser/runtime/override-store.js +52 -0
  59. package/dist/browser/runtime/planner-prompt.js +67 -0
  60. package/dist/browser/runtime/planner-tools.js +77 -0
  61. package/dist/browser/runtime/policy-eval.js +155 -0
  62. package/dist/browser/runtime/preference-adapter.js +67 -0
  63. package/dist/browser/runtime/resolve-bundle.js +767 -0
  64. package/dist/browser/runtime/resolve-preferences.js +59 -0
  65. package/dist/browser/runtime/rollback.js +347 -0
  66. package/dist/browser/runtime/widget-registry.js +36 -0
  67. package/dist/browser/spec/define-module-bundle.js +113 -0
  68. package/dist/browser/spec/index.js +319 -0
  69. package/dist/browser/spec/types.js +0 -0
  70. package/dist/browser/spec/validate-bundle.js +65 -0
  71. package/dist/browser/spec/validate-surface-patch.js +206 -0
  72. package/dist/browser/spec/verification-snapshot-types.js +0 -0
  73. package/dist/browser/telemetry/index.js +20 -0
  74. package/dist/browser/telemetry/surface-metrics.js +20 -0
  75. package/dist/evals/golden-context.d.ts +24 -0
  76. package/dist/evals/golden-context.js +1 -0
  77. package/dist/evals/golden-harness.d.ts +29 -0
  78. package/dist/evals/golden-harness.js +849 -0
  79. package/dist/evals/golden-harness.test.d.ts +1 -0
  80. package/dist/examples/pm-workbench.bundle.d.ts +177 -0
  81. package/dist/examples/pm-workbench.bundle.js +477 -0
  82. package/dist/i18n/catalogs/en.d.ts +1 -0
  83. package/dist/i18n/catalogs/en.js +72 -0
  84. package/dist/i18n/catalogs/es.d.ts +1 -0
  85. package/dist/i18n/catalogs/es.js +33 -0
  86. package/dist/i18n/catalogs/fr.d.ts +1 -0
  87. package/dist/i18n/catalogs/fr.js +33 -0
  88. package/dist/i18n/catalogs/index.d.ts +3 -0
  89. package/dist/i18n/catalogs/index.js +134 -0
  90. package/dist/i18n/index.d.ts +5 -0
  91. package/dist/i18n/index.js +174 -0
  92. package/dist/i18n/keys.d.ts +20 -0
  93. package/dist/i18n/keys.js +20 -0
  94. package/dist/i18n/messages.d.ts +5 -0
  95. package/dist/i18n/messages.js +144 -0
  96. package/dist/index.d.ts +4 -0
  97. package/dist/index.js +2467 -0
  98. package/dist/node/adapters/ai-sdk-stub.js +12 -0
  99. package/dist/node/adapters/blocknote-stub.js +30 -0
  100. package/dist/node/adapters/dnd-kit-adapter.js +43 -0
  101. package/dist/node/adapters/dnd-kit-stub.js +7 -0
  102. package/dist/node/adapters/floating-ui-stub.js +18 -0
  103. package/dist/node/adapters/index.js +175 -0
  104. package/dist/node/adapters/interfaces.js +0 -0
  105. package/dist/node/adapters/motion-stub.js +26 -0
  106. package/dist/node/adapters/resizable-panels-stub.js +45 -0
  107. package/dist/node/evals/golden-context.js +0 -0
  108. package/dist/node/evals/golden-harness.js +848 -0
  109. package/dist/node/examples/pm-workbench.bundle.js +476 -0
  110. package/dist/node/i18n/catalogs/en.js +71 -0
  111. package/dist/node/i18n/catalogs/es.js +32 -0
  112. package/dist/node/i18n/catalogs/fr.js +32 -0
  113. package/dist/node/i18n/catalogs/index.js +133 -0
  114. package/dist/node/i18n/index.js +173 -0
  115. package/dist/node/i18n/keys.js +19 -0
  116. package/dist/node/i18n/messages.js +143 -0
  117. package/dist/node/index.js +2466 -0
  118. package/dist/node/react/BundleProvider.js +47 -0
  119. package/dist/node/react/BundleRenderer.js +726 -0
  120. package/dist/node/react/OverlayConflictResolver.js +255 -0
  121. package/dist/node/react/PatchProposalCard.js +255 -0
  122. package/dist/node/react/RegionRenderer.js +128 -0
  123. package/dist/node/react/SlotRenderer.js +118 -0
  124. package/dist/node/react/WidgetPalette.js +59 -0
  125. package/dist/node/react/index.js +792 -0
  126. package/dist/node/runtime/apply-surface-patch.js +322 -0
  127. package/dist/node/runtime/audit-events.js +137 -0
  128. package/dist/node/runtime/build-context.js +55 -0
  129. package/dist/node/runtime/extension-registry.js +58 -0
  130. package/dist/node/runtime/field-renderer-registry.js +145 -0
  131. package/dist/node/runtime/index.js +1496 -0
  132. package/dist/node/runtime/overlay-alignment.js +83 -0
  133. package/dist/node/runtime/overlay-signer.js +15 -0
  134. package/dist/node/runtime/override-store.js +52 -0
  135. package/dist/node/runtime/planner-prompt.js +67 -0
  136. package/dist/node/runtime/planner-tools.js +77 -0
  137. package/dist/node/runtime/policy-eval.js +155 -0
  138. package/dist/node/runtime/preference-adapter.js +67 -0
  139. package/dist/node/runtime/resolve-bundle.js +767 -0
  140. package/dist/node/runtime/resolve-preferences.js +59 -0
  141. package/dist/node/runtime/rollback.js +347 -0
  142. package/dist/node/runtime/widget-registry.js +36 -0
  143. package/dist/node/spec/define-module-bundle.js +113 -0
  144. package/dist/node/spec/index.js +319 -0
  145. package/dist/node/spec/types.js +0 -0
  146. package/dist/node/spec/validate-bundle.js +65 -0
  147. package/dist/node/spec/validate-surface-patch.js +206 -0
  148. package/dist/node/spec/verification-snapshot-types.js +0 -0
  149. package/dist/node/telemetry/index.js +20 -0
  150. package/dist/node/telemetry/surface-metrics.js +20 -0
  151. package/dist/react/BundleProvider.d.ts +13 -0
  152. package/dist/react/BundleProvider.js +48 -0
  153. package/dist/react/BundleRenderer.d.ts +22 -0
  154. package/dist/react/BundleRenderer.js +727 -0
  155. package/dist/react/OverlayConflictResolver.d.ts +15 -0
  156. package/dist/react/OverlayConflictResolver.js +256 -0
  157. package/dist/react/PatchProposalCard.d.ts +13 -0
  158. package/dist/react/PatchProposalCard.js +256 -0
  159. package/dist/react/RegionRenderer.d.ts +13 -0
  160. package/dist/react/RegionRenderer.js +129 -0
  161. package/dist/react/SlotRenderer.d.ts +13 -0
  162. package/dist/react/SlotRenderer.js +119 -0
  163. package/dist/react/WidgetPalette.d.ts +12 -0
  164. package/dist/react/WidgetPalette.js +60 -0
  165. package/dist/react/index.d.ts +7 -0
  166. package/dist/react/index.js +793 -0
  167. package/dist/runtime/apply-surface-patch.d.ts +15 -0
  168. package/dist/runtime/apply-surface-patch.js +323 -0
  169. package/dist/runtime/apply-surface-patch.test.d.ts +1 -0
  170. package/dist/runtime/audit-events.d.ts +70 -0
  171. package/dist/runtime/audit-events.js +138 -0
  172. package/dist/runtime/audit-events.test.d.ts +1 -0
  173. package/dist/runtime/build-context.d.ts +9 -0
  174. package/dist/runtime/build-context.js +56 -0
  175. package/dist/runtime/extension-registry.d.ts +39 -0
  176. package/dist/runtime/extension-registry.js +59 -0
  177. package/dist/runtime/field-renderer-registry.d.ts +23 -0
  178. package/dist/runtime/field-renderer-registry.js +146 -0
  179. package/dist/runtime/field-renderer-registry.test.d.ts +1 -0
  180. package/dist/runtime/index.d.ts +16 -0
  181. package/dist/runtime/index.js +1497 -0
  182. package/dist/runtime/overlay-alignment.d.ts +49 -0
  183. package/dist/runtime/overlay-alignment.js +84 -0
  184. package/dist/runtime/overlay-alignment.test.d.ts +1 -0
  185. package/dist/runtime/overlay-signer.d.ts +15 -0
  186. package/dist/runtime/overlay-signer.js +16 -0
  187. package/dist/runtime/override-store.d.ts +44 -0
  188. package/dist/runtime/override-store.js +53 -0
  189. package/dist/runtime/override-store.test.d.ts +1 -0
  190. package/dist/runtime/planner-prompt.d.ts +39 -0
  191. package/dist/runtime/planner-prompt.js +68 -0
  192. package/dist/runtime/planner-prompt.test.d.ts +1 -0
  193. package/dist/runtime/planner-tools.d.ts +106 -0
  194. package/dist/runtime/planner-tools.js +78 -0
  195. package/dist/runtime/planner-tools.test.d.ts +1 -0
  196. package/dist/runtime/policy-eval.d.ts +23 -0
  197. package/dist/runtime/policy-eval.js +156 -0
  198. package/dist/runtime/preference-adapter.d.ts +6 -0
  199. package/dist/runtime/preference-adapter.js +68 -0
  200. package/dist/runtime/resolve-bundle.d.ts +68 -0
  201. package/dist/runtime/resolve-bundle.js +768 -0
  202. package/dist/runtime/resolve-bundle.test.d.ts +1 -0
  203. package/dist/runtime/resolve-preferences.d.ts +9 -0
  204. package/dist/runtime/resolve-preferences.js +60 -0
  205. package/dist/runtime/resolve-preferences.test.d.ts +1 -0
  206. package/dist/runtime/rollback.d.ts +21 -0
  207. package/dist/runtime/rollback.js +348 -0
  208. package/dist/runtime/rollback.test.d.ts +1 -0
  209. package/dist/runtime/widget-registry.d.ts +26 -0
  210. package/dist/runtime/widget-registry.js +37 -0
  211. package/dist/runtime/widget-registry.test.d.ts +1 -0
  212. package/dist/spec/define-module-bundle.d.ts +17 -0
  213. package/dist/spec/define-module-bundle.js +114 -0
  214. package/dist/spec/define-module-bundle.test.d.ts +1 -0
  215. package/dist/spec/index.d.ts +5 -0
  216. package/dist/spec/index.js +320 -0
  217. package/dist/spec/types.d.ts +494 -0
  218. package/dist/spec/types.js +1 -0
  219. package/dist/spec/validate-bundle.d.ts +23 -0
  220. package/dist/spec/validate-bundle.js +66 -0
  221. package/dist/spec/validate-bundle.test.d.ts +1 -0
  222. package/dist/spec/validate-surface-patch.d.ts +39 -0
  223. package/dist/spec/validate-surface-patch.js +207 -0
  224. package/dist/spec/validate-surface-patch.test.d.ts +1 -0
  225. package/dist/spec/verification-snapshot-types.d.ts +23 -0
  226. package/dist/spec/verification-snapshot-types.js +1 -0
  227. package/dist/spec/verification-snapshot.test.d.ts +5 -0
  228. package/dist/telemetry/index.d.ts +5 -0
  229. package/dist/telemetry/index.js +21 -0
  230. package/dist/telemetry/surface-metrics.d.ts +17 -0
  231. package/dist/telemetry/surface-metrics.js +21 -0
  232. package/package.json +920 -0
@@ -0,0 +1,15 @@
1
+ import type { OverlayConflict } from '../runtime/resolve-bundle';
2
+ export interface OverlayConflictResolverProps {
3
+ conflicts: OverlayConflict[];
4
+ onResolve: (resolution: {
5
+ targetKey: string;
6
+ chosenScope: 'A' | 'B';
7
+ }) => void;
8
+ /** Locale for i18n (e.g. from plan.locale). Defaults to 'en'. */
9
+ locale?: string;
10
+ }
11
+ /**
12
+ * Renders overlay merge conflicts and lets the user choose which overlay wins.
13
+ * Simplified: keep higher-trust scope (workspace > user > session).
14
+ */
15
+ export declare function OverlayConflictResolver({ conflicts, onResolve, locale, }: OverlayConflictResolverProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,256 @@
1
+ // @bun
2
+ // src/i18n/catalogs/en.ts
3
+ import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
4
+ var enMessages = defineTranslation({
5
+ meta: {
6
+ key: "surface-runtime.messages",
7
+ version: "1.0.0",
8
+ domain: "surface-runtime",
9
+ description: "User-facing strings for surface-runtime UI components",
10
+ owners: ["platform"],
11
+ stability: "experimental"
12
+ },
13
+ locale: "en",
14
+ fallback: "en",
15
+ messages: {
16
+ "overlay.conflicts.title": {
17
+ value: "Overlay conflicts",
18
+ description: "Title for overlay conflict resolution banner"
19
+ },
20
+ "overlay.conflicts.keepScope": {
21
+ value: "Keep {scope}",
22
+ description: "Button to keep overlay from scope A or B"
23
+ },
24
+ "patch.accept": {
25
+ value: "Accept",
26
+ description: "Accept patch proposal button"
27
+ },
28
+ "patch.reject": {
29
+ value: "Reject",
30
+ description: "Reject patch proposal button"
31
+ },
32
+ "patch.addWidget": {
33
+ value: "Add {title} to {slot}",
34
+ description: "Insert node proposal summary"
35
+ },
36
+ "patch.removeItem": {
37
+ value: "Remove item",
38
+ description: "Remove node proposal summary"
39
+ },
40
+ "patch.switchLayout": {
41
+ value: "Switch to {layoutId} layout",
42
+ description: "Set layout proposal summary"
43
+ },
44
+ "patch.showField": {
45
+ value: "Show field {fieldId}",
46
+ description: "Reveal field proposal summary"
47
+ },
48
+ "patch.hideField": {
49
+ value: "Hide field {fieldId}",
50
+ description: "Hide field proposal summary"
51
+ },
52
+ "patch.moveTo": {
53
+ value: "Move to {slot}",
54
+ description: "Move node proposal summary"
55
+ },
56
+ "patch.replaceItem": {
57
+ value: "Replace item",
58
+ description: "Replace node proposal summary"
59
+ },
60
+ "patch.promote": {
61
+ value: "Promote {actionId}",
62
+ description: "Promote action proposal summary"
63
+ },
64
+ "patch.changes": {
65
+ value: "{count} changes",
66
+ description: "Multiple patch ops summary"
67
+ }
68
+ }
69
+ });
70
+
71
+ // src/i18n/catalogs/es.ts
72
+ import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
73
+ var esMessages = defineTranslation2({
74
+ meta: {
75
+ key: "surface-runtime.messages",
76
+ version: "1.0.0",
77
+ domain: "surface-runtime",
78
+ description: "User-facing strings for surface-runtime UI components",
79
+ owners: ["platform"],
80
+ stability: "experimental"
81
+ },
82
+ locale: "es",
83
+ fallback: "en",
84
+ messages: {
85
+ "overlay.conflicts.title": { value: "Conflictos de superposici\xF3n" },
86
+ "overlay.conflicts.keepScope": { value: "Mantener {scope}" },
87
+ "patch.accept": { value: "Aceptar" },
88
+ "patch.reject": { value: "Rechazar" },
89
+ "patch.addWidget": { value: "A\xF1adir {title} a {slot}" },
90
+ "patch.removeItem": { value: "Eliminar elemento" },
91
+ "patch.switchLayout": { value: "Cambiar a disposici\xF3n {layoutId}" },
92
+ "patch.showField": { value: "Mostrar campo {fieldId}" },
93
+ "patch.hideField": { value: "Ocultar campo {fieldId}" },
94
+ "patch.moveTo": { value: "Mover a {slot}" },
95
+ "patch.replaceItem": { value: "Reemplazar elemento" },
96
+ "patch.promote": { value: "Promover {actionId}" },
97
+ "patch.changes": { value: "{count} cambios" }
98
+ }
99
+ });
100
+
101
+ // src/i18n/catalogs/fr.ts
102
+ import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
103
+ var frMessages = defineTranslation3({
104
+ meta: {
105
+ key: "surface-runtime.messages",
106
+ version: "1.0.0",
107
+ domain: "surface-runtime",
108
+ description: "User-facing strings for surface-runtime UI components",
109
+ owners: ["platform"],
110
+ stability: "experimental"
111
+ },
112
+ locale: "fr",
113
+ fallback: "en",
114
+ messages: {
115
+ "overlay.conflicts.title": { value: "Conflits de superposition" },
116
+ "overlay.conflicts.keepScope": { value: "Conserver {scope}" },
117
+ "patch.accept": { value: "Accepter" },
118
+ "patch.reject": { value: "Rejeter" },
119
+ "patch.addWidget": { value: "Ajouter {title} \xE0 {slot}" },
120
+ "patch.removeItem": { value: "Supprimer l'\xE9l\xE9ment" },
121
+ "patch.switchLayout": { value: "Passer \xE0 la disposition {layoutId}" },
122
+ "patch.showField": { value: "Afficher le champ {fieldId}" },
123
+ "patch.hideField": { value: "Masquer le champ {fieldId}" },
124
+ "patch.moveTo": { value: "D\xE9placer vers {slot}" },
125
+ "patch.replaceItem": { value: "Remplacer l'\xE9l\xE9ment" },
126
+ "patch.promote": { value: "Promouvoir {actionId}" },
127
+ "patch.changes": { value: "{count} modifications" }
128
+ }
129
+ });
130
+
131
+ // src/i18n/messages.ts
132
+ import {
133
+ createI18nFactory
134
+ } from "@contractspec/lib.contracts-spec/translations";
135
+ var factory = createI18nFactory({
136
+ specKey: "surface-runtime.messages",
137
+ catalogs: [enMessages, frMessages, esMessages]
138
+ });
139
+ var createSurfaceI18n = factory.create;
140
+ var getDefaultSurfaceI18n = factory.getDefault;
141
+
142
+ // src/i18n/keys.ts
143
+ var SURFACE_KEYS = {
144
+ "overlay.conflicts.title": "overlay.conflicts.title",
145
+ "overlay.conflicts.keepScope": "overlay.conflicts.keepScope",
146
+ "patch.accept": "patch.accept",
147
+ "patch.reject": "patch.reject",
148
+ "patch.addWidget": "patch.addWidget",
149
+ "patch.removeItem": "patch.removeItem",
150
+ "patch.switchLayout": "patch.switchLayout",
151
+ "patch.showField": "patch.showField",
152
+ "patch.hideField": "patch.hideField",
153
+ "patch.moveTo": "patch.moveTo",
154
+ "patch.replaceItem": "patch.replaceItem",
155
+ "patch.promote": "patch.promote",
156
+ "patch.changes": "patch.changes"
157
+ };
158
+
159
+ // src/i18n/index.ts
160
+ import {
161
+ resolveLocale,
162
+ isSupportedLocale,
163
+ DEFAULT_LOCALE,
164
+ SUPPORTED_LOCALES
165
+ } from "@contractspec/lib.contracts-spec/translations";
166
+
167
+ // src/react/OverlayConflictResolver.tsx
168
+ import { useMemo } from "react";
169
+ import { jsxDEV } from "react/jsx-dev-runtime";
170
+ "use client";
171
+ function OverlayConflictResolver({
172
+ conflicts,
173
+ onResolve,
174
+ locale
175
+ }) {
176
+ const i18n = useMemo(() => createSurfaceI18n(locale), [locale]);
177
+ return /* @__PURE__ */ jsxDEV("div", {
178
+ "data-overlay-conflicts": true,
179
+ style: {
180
+ padding: "12px",
181
+ marginBottom: "12px",
182
+ border: "1px solid var(--destructive, #ef4444)",
183
+ borderRadius: "8px",
184
+ backgroundColor: "var(--destructive/10, #fef2f2)"
185
+ },
186
+ children: [
187
+ /* @__PURE__ */ jsxDEV("div", {
188
+ style: {
189
+ fontSize: "14px",
190
+ fontWeight: 600,
191
+ marginBottom: "8px",
192
+ color: "var(--destructive, #ef4444)"
193
+ },
194
+ children: i18n.t("overlay.conflicts.title")
195
+ }, undefined, false, undefined, this),
196
+ conflicts.map((c) => /* @__PURE__ */ jsxDEV("div", {
197
+ style: {
198
+ padding: "8px",
199
+ marginBottom: "8px",
200
+ backgroundColor: "white",
201
+ borderRadius: "4px",
202
+ fontSize: "13px"
203
+ },
204
+ children: [
205
+ /* @__PURE__ */ jsxDEV("span", {
206
+ children: c.targetKey
207
+ }, undefined, false, undefined, this),
208
+ /* @__PURE__ */ jsxDEV("span", {
209
+ style: { margin: "0 8px", color: "#9ca3af" },
210
+ children: [
211
+ "(",
212
+ c.scopeA,
213
+ " vs ",
214
+ c.scopeB,
215
+ ")"
216
+ ]
217
+ }, undefined, true, undefined, this),
218
+ /* @__PURE__ */ jsxDEV("div", {
219
+ style: { marginTop: "8px", display: "flex", gap: "8px" },
220
+ children: [
221
+ /* @__PURE__ */ jsxDEV("button", {
222
+ type: "button",
223
+ onClick: () => onResolve({ targetKey: c.targetKey, chosenScope: "A" }),
224
+ style: {
225
+ padding: "4px 12px",
226
+ fontSize: "12px",
227
+ borderRadius: "4px",
228
+ border: "1px solid #e5e7eb",
229
+ backgroundColor: "white",
230
+ cursor: "pointer"
231
+ },
232
+ children: i18n.t("overlay.conflicts.keepScope", { scope: c.scopeA })
233
+ }, undefined, false, undefined, this),
234
+ /* @__PURE__ */ jsxDEV("button", {
235
+ type: "button",
236
+ onClick: () => onResolve({ targetKey: c.targetKey, chosenScope: "B" }),
237
+ style: {
238
+ padding: "4px 12px",
239
+ fontSize: "12px",
240
+ borderRadius: "4px",
241
+ border: "1px solid #e5e7eb",
242
+ backgroundColor: "white",
243
+ cursor: "pointer"
244
+ },
245
+ children: i18n.t("overlay.conflicts.keepScope", { scope: c.scopeB })
246
+ }, undefined, false, undefined, this)
247
+ ]
248
+ }, undefined, true, undefined, this)
249
+ ]
250
+ }, `${c.targetKey}-${c.overlayIdA}-${c.overlayIdB}`, true, undefined, this))
251
+ ]
252
+ }, undefined, true, undefined, this);
253
+ }
254
+ export {
255
+ OverlayConflictResolver
256
+ };
@@ -0,0 +1,13 @@
1
+ import type { SurfacePatchProposal } from '../spec/types';
2
+ export interface PatchProposalCardProps {
3
+ proposal: SurfacePatchProposal;
4
+ onAccept: (proposalId: string) => void;
5
+ onReject: (proposalId: string, reason?: string) => void;
6
+ /** Locale for i18n (e.g. from plan.locale). Defaults to 'en'. */
7
+ locale?: string;
8
+ }
9
+ /**
10
+ * Renders a single patch proposal with Accept and Reject actions.
11
+ * Used when the assistant proposes surface changes (e.g. insert widget, change layout).
12
+ */
13
+ export declare function PatchProposalCard({ proposal, onAccept, onReject, locale, }: PatchProposalCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,256 @@
1
+ // @bun
2
+ // src/i18n/catalogs/en.ts
3
+ import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
4
+ var enMessages = defineTranslation({
5
+ meta: {
6
+ key: "surface-runtime.messages",
7
+ version: "1.0.0",
8
+ domain: "surface-runtime",
9
+ description: "User-facing strings for surface-runtime UI components",
10
+ owners: ["platform"],
11
+ stability: "experimental"
12
+ },
13
+ locale: "en",
14
+ fallback: "en",
15
+ messages: {
16
+ "overlay.conflicts.title": {
17
+ value: "Overlay conflicts",
18
+ description: "Title for overlay conflict resolution banner"
19
+ },
20
+ "overlay.conflicts.keepScope": {
21
+ value: "Keep {scope}",
22
+ description: "Button to keep overlay from scope A or B"
23
+ },
24
+ "patch.accept": {
25
+ value: "Accept",
26
+ description: "Accept patch proposal button"
27
+ },
28
+ "patch.reject": {
29
+ value: "Reject",
30
+ description: "Reject patch proposal button"
31
+ },
32
+ "patch.addWidget": {
33
+ value: "Add {title} to {slot}",
34
+ description: "Insert node proposal summary"
35
+ },
36
+ "patch.removeItem": {
37
+ value: "Remove item",
38
+ description: "Remove node proposal summary"
39
+ },
40
+ "patch.switchLayout": {
41
+ value: "Switch to {layoutId} layout",
42
+ description: "Set layout proposal summary"
43
+ },
44
+ "patch.showField": {
45
+ value: "Show field {fieldId}",
46
+ description: "Reveal field proposal summary"
47
+ },
48
+ "patch.hideField": {
49
+ value: "Hide field {fieldId}",
50
+ description: "Hide field proposal summary"
51
+ },
52
+ "patch.moveTo": {
53
+ value: "Move to {slot}",
54
+ description: "Move node proposal summary"
55
+ },
56
+ "patch.replaceItem": {
57
+ value: "Replace item",
58
+ description: "Replace node proposal summary"
59
+ },
60
+ "patch.promote": {
61
+ value: "Promote {actionId}",
62
+ description: "Promote action proposal summary"
63
+ },
64
+ "patch.changes": {
65
+ value: "{count} changes",
66
+ description: "Multiple patch ops summary"
67
+ }
68
+ }
69
+ });
70
+
71
+ // src/i18n/catalogs/es.ts
72
+ import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
73
+ var esMessages = defineTranslation2({
74
+ meta: {
75
+ key: "surface-runtime.messages",
76
+ version: "1.0.0",
77
+ domain: "surface-runtime",
78
+ description: "User-facing strings for surface-runtime UI components",
79
+ owners: ["platform"],
80
+ stability: "experimental"
81
+ },
82
+ locale: "es",
83
+ fallback: "en",
84
+ messages: {
85
+ "overlay.conflicts.title": { value: "Conflictos de superposici\xF3n" },
86
+ "overlay.conflicts.keepScope": { value: "Mantener {scope}" },
87
+ "patch.accept": { value: "Aceptar" },
88
+ "patch.reject": { value: "Rechazar" },
89
+ "patch.addWidget": { value: "A\xF1adir {title} a {slot}" },
90
+ "patch.removeItem": { value: "Eliminar elemento" },
91
+ "patch.switchLayout": { value: "Cambiar a disposici\xF3n {layoutId}" },
92
+ "patch.showField": { value: "Mostrar campo {fieldId}" },
93
+ "patch.hideField": { value: "Ocultar campo {fieldId}" },
94
+ "patch.moveTo": { value: "Mover a {slot}" },
95
+ "patch.replaceItem": { value: "Reemplazar elemento" },
96
+ "patch.promote": { value: "Promover {actionId}" },
97
+ "patch.changes": { value: "{count} cambios" }
98
+ }
99
+ });
100
+
101
+ // src/i18n/catalogs/fr.ts
102
+ import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
103
+ var frMessages = defineTranslation3({
104
+ meta: {
105
+ key: "surface-runtime.messages",
106
+ version: "1.0.0",
107
+ domain: "surface-runtime",
108
+ description: "User-facing strings for surface-runtime UI components",
109
+ owners: ["platform"],
110
+ stability: "experimental"
111
+ },
112
+ locale: "fr",
113
+ fallback: "en",
114
+ messages: {
115
+ "overlay.conflicts.title": { value: "Conflits de superposition" },
116
+ "overlay.conflicts.keepScope": { value: "Conserver {scope}" },
117
+ "patch.accept": { value: "Accepter" },
118
+ "patch.reject": { value: "Rejeter" },
119
+ "patch.addWidget": { value: "Ajouter {title} \xE0 {slot}" },
120
+ "patch.removeItem": { value: "Supprimer l'\xE9l\xE9ment" },
121
+ "patch.switchLayout": { value: "Passer \xE0 la disposition {layoutId}" },
122
+ "patch.showField": { value: "Afficher le champ {fieldId}" },
123
+ "patch.hideField": { value: "Masquer le champ {fieldId}" },
124
+ "patch.moveTo": { value: "D\xE9placer vers {slot}" },
125
+ "patch.replaceItem": { value: "Remplacer l'\xE9l\xE9ment" },
126
+ "patch.promote": { value: "Promouvoir {actionId}" },
127
+ "patch.changes": { value: "{count} modifications" }
128
+ }
129
+ });
130
+
131
+ // src/i18n/messages.ts
132
+ import {
133
+ createI18nFactory
134
+ } from "@contractspec/lib.contracts-spec/translations";
135
+ var factory = createI18nFactory({
136
+ specKey: "surface-runtime.messages",
137
+ catalogs: [enMessages, frMessages, esMessages]
138
+ });
139
+ var createSurfaceI18n = factory.create;
140
+ var getDefaultSurfaceI18n = factory.getDefault;
141
+
142
+ // src/i18n/keys.ts
143
+ var SURFACE_KEYS = {
144
+ "overlay.conflicts.title": "overlay.conflicts.title",
145
+ "overlay.conflicts.keepScope": "overlay.conflicts.keepScope",
146
+ "patch.accept": "patch.accept",
147
+ "patch.reject": "patch.reject",
148
+ "patch.addWidget": "patch.addWidget",
149
+ "patch.removeItem": "patch.removeItem",
150
+ "patch.switchLayout": "patch.switchLayout",
151
+ "patch.showField": "patch.showField",
152
+ "patch.hideField": "patch.hideField",
153
+ "patch.moveTo": "patch.moveTo",
154
+ "patch.replaceItem": "patch.replaceItem",
155
+ "patch.promote": "patch.promote",
156
+ "patch.changes": "patch.changes"
157
+ };
158
+
159
+ // src/i18n/index.ts
160
+ import {
161
+ resolveLocale,
162
+ isSupportedLocale,
163
+ DEFAULT_LOCALE,
164
+ SUPPORTED_LOCALES
165
+ } from "@contractspec/lib.contracts-spec/translations";
166
+
167
+ // src/react/PatchProposalCard.tsx
168
+ import { useMemo } from "react";
169
+ import { jsxDEV } from "react/jsx-dev-runtime";
170
+ "use client";
171
+ function PatchProposalCard({
172
+ proposal,
173
+ onAccept,
174
+ onReject,
175
+ locale
176
+ }) {
177
+ const i18n = useMemo(() => createSurfaceI18n(locale), [locale]);
178
+ const firstOp = proposal.ops[0];
179
+ const summary = proposal.ops.length === 1 && firstOp ? describeOp(firstOp, i18n) : i18n.t("patch.changes", { count: proposal.ops.length });
180
+ return /* @__PURE__ */ jsxDEV("div", {
181
+ "data-proposal-id": proposal.proposalId,
182
+ style: {
183
+ padding: "12px",
184
+ border: "1px solid var(--border, #e5e7eb)",
185
+ borderRadius: "8px",
186
+ marginBottom: "8px",
187
+ backgroundColor: "var(--muted, #f9fafb)"
188
+ },
189
+ children: [
190
+ /* @__PURE__ */ jsxDEV("div", {
191
+ style: { marginBottom: "8px", fontSize: "14px" },
192
+ children: summary
193
+ }, undefined, false, undefined, this),
194
+ /* @__PURE__ */ jsxDEV("div", {
195
+ style: { display: "flex", gap: "8px" },
196
+ children: [
197
+ /* @__PURE__ */ jsxDEV("button", {
198
+ type: "button",
199
+ onClick: () => onAccept(proposal.proposalId),
200
+ style: {
201
+ padding: "4px 12px",
202
+ fontSize: "13px",
203
+ borderRadius: "4px",
204
+ border: "none",
205
+ backgroundColor: "var(--primary, #3b82f6)",
206
+ color: "white",
207
+ cursor: "pointer"
208
+ },
209
+ children: i18n.t("patch.accept")
210
+ }, undefined, false, undefined, this),
211
+ /* @__PURE__ */ jsxDEV("button", {
212
+ type: "button",
213
+ onClick: () => onReject(proposal.proposalId),
214
+ style: {
215
+ padding: "4px 12px",
216
+ fontSize: "13px",
217
+ borderRadius: "4px",
218
+ border: "1px solid var(--border, #e5e7eb)",
219
+ backgroundColor: "transparent",
220
+ cursor: "pointer"
221
+ },
222
+ children: i18n.t("patch.reject")
223
+ }, undefined, false, undefined, this)
224
+ ]
225
+ }, undefined, true, undefined, this)
226
+ ]
227
+ }, undefined, true, undefined, this);
228
+ }
229
+ function describeOp(op, i18n) {
230
+ switch (op.op) {
231
+ case "insert-node":
232
+ return i18n.t("patch.addWidget", {
233
+ title: op.node?.title ?? op.node?.kind ?? "widget",
234
+ slot: op.slotId ?? "slot"
235
+ });
236
+ case "remove-node":
237
+ return i18n.t("patch.removeItem");
238
+ case "set-layout":
239
+ return i18n.t("patch.switchLayout", { layoutId: op.layoutId });
240
+ case "reveal-field":
241
+ return i18n.t("patch.showField", { fieldId: op.fieldId });
242
+ case "hide-field":
243
+ return i18n.t("patch.hideField", { fieldId: op.fieldId });
244
+ case "move-node":
245
+ return i18n.t("patch.moveTo", { slot: op.toSlotId ?? "slot" });
246
+ case "replace-node":
247
+ return i18n.t("patch.replaceItem");
248
+ case "promote-action":
249
+ return i18n.t("patch.promote", { actionId: op.actionId });
250
+ default:
251
+ return `${op.op}`;
252
+ }
253
+ }
254
+ export {
255
+ PatchProposalCard
256
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Recursively renders a RegionNode (layout tree).
3
+ * Delegates panel-group to adapter; handles stack, tabs, slot, floating.
4
+ */
5
+ import React from 'react';
6
+ import type { RegionNode } from '../spec/types';
7
+ import type { RenderContext } from '../adapters/interfaces';
8
+ export interface RegionRendererProps {
9
+ region: RegionNode;
10
+ ctx: RenderContext;
11
+ renderSlot: (slotId: string, ctx: RenderContext) => React.ReactNode;
12
+ }
13
+ export declare function RegionRenderer({ region, ctx, renderSlot, }: RegionRendererProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,129 @@
1
+ // @bun
2
+ // src/adapters/resizable-panels-stub.tsx
3
+ import { jsxDEV } from "react/jsx-dev-runtime";
4
+ var LAYOUT_STORAGE_KEY = "surface-runtime:panel-layout:";
5
+ var resizablePanelsAdapterStub = {
6
+ renderPanelGroup(region, ctx, renderChild) {
7
+ const direction = region.direction === "horizontal" ? "row" : "column";
8
+ return /* @__PURE__ */ jsxDEV("div", {
9
+ "data-panel-group": true,
10
+ "data-persist-key": region.persistKey,
11
+ style: {
12
+ display: "flex",
13
+ flexDirection: direction,
14
+ flex: 1,
15
+ minHeight: 0
16
+ },
17
+ children: region.children.map((child, i) => /* @__PURE__ */ jsxDEV("div", {
18
+ style: { flex: 1, minWidth: 0, minHeight: 0 },
19
+ children: renderChild(child, ctx)
20
+ }, i, false, undefined, this))
21
+ }, undefined, false, undefined, this);
22
+ },
23
+ async restoreLayout(persistKey) {
24
+ if (typeof localStorage === "undefined")
25
+ return null;
26
+ try {
27
+ const raw = localStorage.getItem(LAYOUT_STORAGE_KEY + persistKey);
28
+ if (!raw)
29
+ return null;
30
+ const parsed = JSON.parse(raw);
31
+ return Array.isArray(parsed) ? parsed : null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ },
36
+ async saveLayout(persistKey, sizes) {
37
+ if (typeof localStorage === "undefined")
38
+ return;
39
+ try {
40
+ localStorage.setItem(LAYOUT_STORAGE_KEY + persistKey, JSON.stringify(sizes));
41
+ } catch {}
42
+ }
43
+ };
44
+
45
+ // src/react/RegionRenderer.tsx
46
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
47
+ function RegionRenderer({
48
+ region,
49
+ ctx,
50
+ renderSlot
51
+ }) {
52
+ const renderChild = (child, childCtx) => /* @__PURE__ */ jsxDEV2(RegionRenderer, {
53
+ region: child,
54
+ ctx: childCtx,
55
+ renderSlot
56
+ }, undefined, false, undefined, this);
57
+ switch (region.type) {
58
+ case "panel-group":
59
+ return resizablePanelsAdapterStub.renderPanelGroup(region, ctx, renderChild);
60
+ case "stack": {
61
+ const direction = region.direction === "horizontal" ? "row" : "column";
62
+ const gapMap = {
63
+ none: 0,
64
+ xs: 4,
65
+ sm: 8,
66
+ md: 16,
67
+ lg: 24
68
+ };
69
+ const gap = gapMap[region.gap ?? "md"];
70
+ return /* @__PURE__ */ jsxDEV2("div", {
71
+ "data-region": "stack",
72
+ style: {
73
+ display: "flex",
74
+ flexDirection: direction,
75
+ gap,
76
+ flex: 1,
77
+ minHeight: 0
78
+ },
79
+ children: region.children.map((child, i) => /* @__PURE__ */ jsxDEV2("div", {
80
+ style: { flex: 1, minWidth: 0, minHeight: 0 },
81
+ children: /* @__PURE__ */ jsxDEV2(RegionRenderer, {
82
+ region: child,
83
+ ctx,
84
+ renderSlot
85
+ }, undefined, false, undefined, this)
86
+ }, i, false, undefined, this))
87
+ }, undefined, false, undefined, this);
88
+ }
89
+ case "tabs":
90
+ return /* @__PURE__ */ jsxDEV2("div", {
91
+ "data-region": "tabs",
92
+ children: [
93
+ /* @__PURE__ */ jsxDEV2("div", {
94
+ role: "tablist",
95
+ children: region.tabs.map((t) => /* @__PURE__ */ jsxDEV2("button", {
96
+ type: "button",
97
+ role: "tab",
98
+ children: t.title
99
+ }, t.key, false, undefined, this))
100
+ }, undefined, false, undefined, this),
101
+ region.tabs[0] && /* @__PURE__ */ jsxDEV2(RegionRenderer, {
102
+ region: region.tabs[0].child,
103
+ ctx,
104
+ renderSlot
105
+ }, undefined, false, undefined, this)
106
+ ]
107
+ }, undefined, true, undefined, this);
108
+ case "slot":
109
+ return /* @__PURE__ */ jsxDEV2("div", {
110
+ "data-slot": region.slotId,
111
+ children: renderSlot(region.slotId, ctx)
112
+ }, undefined, false, undefined, this);
113
+ case "floating":
114
+ return /* @__PURE__ */ jsxDEV2("div", {
115
+ "data-floating": true,
116
+ "data-anchor": region.anchorSlotId,
117
+ children: /* @__PURE__ */ jsxDEV2(RegionRenderer, {
118
+ region: region.child,
119
+ ctx,
120
+ renderSlot
121
+ }, undefined, false, undefined, this)
122
+ }, undefined, false, undefined, this);
123
+ default:
124
+ return null;
125
+ }
126
+ }
127
+ export {
128
+ RegionRenderer
129
+ };