bedrock-flows 0.7.1

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 (85) hide show
  1. package/auth-schema.sql +8 -0
  2. package/bin/bedrock-flows.mjs +127 -0
  3. package/lib/setup.mjs +262 -0
  4. package/package.json +11 -0
  5. package/template/.storybook/main.js +46 -0
  6. package/template/.storybook/manager-head.html +963 -0
  7. package/template/.storybook/preview-head.html +35 -0
  8. package/template/.storybook/preview.js +23 -0
  9. package/template/CHANGELOG.md +236 -0
  10. package/template/README.md +26 -0
  11. package/template/apps/dashboard/index.html +15 -0
  12. package/template/apps/dashboard/package.json +22 -0
  13. package/template/apps/dashboard/src/App.module.css +1318 -0
  14. package/template/apps/dashboard/src/App.tsx +2716 -0
  15. package/template/apps/dashboard/src/auth-client.ts +17 -0
  16. package/template/apps/dashboard/src/changelog.tsx +92 -0
  17. package/template/apps/dashboard/src/index.css +86 -0
  18. package/template/apps/dashboard/src/main.tsx +15 -0
  19. package/template/apps/dashboard/src/theme.ts +31 -0
  20. package/template/apps/dashboard/src/vite-env.d.ts +4 -0
  21. package/template/apps/dashboard/vite.config.ts +48 -0
  22. package/template/apps/worker/.dev.vars.example +50 -0
  23. package/template/apps/worker/package.json +19 -0
  24. package/template/apps/worker/src/index.ts +295 -0
  25. package/template/apps/worker/tsconfig.json +11 -0
  26. package/template/apps/worker/wrangler.jsonc +29 -0
  27. package/template/bedrock.config.ts +16 -0
  28. package/template/design-system/README.md +97 -0
  29. package/template/design-system/starter-v1/components/button/component.css +42 -0
  30. package/template/design-system/starter-v1/components/button/danger.html +21 -0
  31. package/template/design-system/starter-v1/components/button/default.html +21 -0
  32. package/template/design-system/starter-v1/components/button/disabled.html +21 -0
  33. package/template/design-system/starter-v1/components/button/ghost.html +21 -0
  34. package/template/design-system/starter-v1/components/button/macro.njk +14 -0
  35. package/template/design-system/starter-v1/components/button/primary.html +21 -0
  36. package/template/design-system/starter-v1/components/button/variants.json +30 -0
  37. package/template/design-system/starter-v1/ds.json +3 -0
  38. package/template/design-system/starter-v1/global.css +52 -0
  39. package/template/design-system/starter-v1/style.css +107 -0
  40. package/template/gitignore +8 -0
  41. package/template/package.json +41 -0
  42. package/template/prototypes/F-001-hello/1-welcome.njk +30 -0
  43. package/template/prototypes/F-001-hello/2-form.njk +46 -0
  44. package/template/prototypes/F-001-hello/3-done.njk +29 -0
  45. package/template/prototypes/F-001-hello/meta.json +6 -0
  46. package/template/prototypes/_shared/_auth-gate.njk +54 -0
  47. package/template/prototypes/_shared/delivery.njk +43 -0
  48. package/template/prototypes/_shared/layout.njk +15 -0
  49. package/template/prototypes/_shared/screen.njk +1818 -0
  50. package/template/prototypes/_shared/wireflow.njk +4731 -0
  51. package/template/public/auth-gate.css +150 -0
  52. package/template/public/bedrock/color-inspector.js +284 -0
  53. package/template/public/bedrock/component-overlay.js +219 -0
  54. package/template/public/bedrock/data/bedrock-config.js +45 -0
  55. package/template/public/bedrock/font-size-overlay.js +590 -0
  56. package/template/public/bedrock/grid-overlay.js +379 -0
  57. package/template/public/bedrock/prototype-navigation.js +974 -0
  58. package/template/public/cmdk.js +146 -0
  59. package/template/public/ds-xray.css +112 -0
  60. package/template/public/ds-xray.js +271 -0
  61. package/template/public/favicon.svg +4 -0
  62. package/template/public/icons/bolt-fill.svg +3 -0
  63. package/template/public/icons/bolt.svg +3 -0
  64. package/template/public/icons/caret-down-fill.svg +3 -0
  65. package/template/public/icons/check-double.svg +4 -0
  66. package/template/public/icons/check.svg +3 -0
  67. package/template/public/icons/chevron-left.svg +3 -0
  68. package/template/public/icons/chevron-right.svg +3 -0
  69. package/template/public/icons/circle-info.svg +6 -0
  70. package/template/public/icons/grid.svg +6 -0
  71. package/template/public/icons/message-square-1.svg +3 -0
  72. package/template/public/icons/message-square.svg +3 -0
  73. package/template/public/icons/messages.svg +4 -0
  74. package/template/public/icons/options-horizontal.svg +5 -0
  75. package/template/public/icons/swatches.svg +6 -0
  76. package/template/public/icons/workflow.svg +6 -0
  77. package/template/public/lightbox.js +87 -0
  78. package/template/public/proto-chrome.css +596 -0
  79. package/template/public/screen-comments.css +723 -0
  80. package/template/public/wireflow-client.js +26 -0
  81. package/template/scripts/build-storybooks.mjs +8 -0
  82. package/template/scripts/dev-setup.mjs +15 -0
  83. package/template/scripts/generate-stories.mjs +12 -0
  84. package/template/scripts/generate-variants.mjs +22 -0
  85. package/template/tsconfig.base.json +19 -0
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Grid Overlay
3
+ *
4
+ * Two modes:
5
+ * 1. Column Grid (Ctrl+Shift+G) — 12-column layout grid, 1440px centered, 40px margin, 24px gutter
6
+ * 2. Section Spacing (Ctrl+Shift+H) — visualizes vertical gaps between direct children of <main>
7
+ *
8
+ * State is persisted in localStorage.
9
+ */
10
+ (function() {
11
+ const STORAGE_KEY_COL = 'gridOverlayEnabled';
12
+ const STORAGE_KEY_SPACING = 'sectionSpacingEnabled';
13
+ const COL_OVERLAY_ID = 'grid-overlay';
14
+ const TOAST_ID = 'grid-overlay-toast';
15
+
16
+ const GRID_WIDTH = 1440;
17
+ const COLUMNS = 12;
18
+ const MARGIN = 40;
19
+ const GUTTER = 24;
20
+
21
+ let colEnabled = false;
22
+ let spacingEnabled = false;
23
+ let colOverlay = null;
24
+ let spacingMarkers = [];
25
+
26
+ // Returns the main content container (proto-nav wrapper or body)
27
+ function getContainer() {
28
+ return document.getElementById('protoSiteWrapper') || document.body;
29
+ }
30
+
31
+ // Returns the scroll offset of the content container
32
+ function getScrollTop() {
33
+ const wrapper = document.getElementById('protoSiteWrapper');
34
+ return wrapper ? wrapper.scrollTop : window.scrollY;
35
+ }
36
+
37
+ // --- Styles ---
38
+ function injectStyles() {
39
+ if (document.getElementById('grid-overlay-styles')) return;
40
+ const style = document.createElement('style');
41
+ style.id = 'grid-overlay-styles';
42
+ style.textContent = `
43
+ #${COL_OVERLAY_ID} {
44
+ position: absolute;
45
+ top: 0;
46
+ left: 50%;
47
+ transform: translateX(-50%);
48
+ width: ${GRID_WIDTH}px;
49
+ max-width: 100%;
50
+ min-height: 100%;
51
+ pointer-events: none;
52
+ z-index: 99989;
53
+ display: flex;
54
+ align-items: flex-start;
55
+ padding: 0 ${MARGIN}px;
56
+ box-sizing: border-box;
57
+ gap: ${GUTTER}px;
58
+ }
59
+ #${COL_OVERLAY_ID} .grid-overlay__column {
60
+ flex: 1;
61
+ min-height: 100%;
62
+ background: rgba(220, 38, 38, 0.1);
63
+ border-left: 1px solid rgba(220, 38, 38, 0.3);
64
+ border-right: 1px solid rgba(220, 38, 38, 0.3);
65
+ box-sizing: border-box;
66
+ }
67
+ .section-gap-marker {
68
+ position: absolute;
69
+ left: 0;
70
+ width: 100%;
71
+ pointer-events: none;
72
+ z-index: 99988;
73
+ box-sizing: border-box;
74
+ }
75
+ .section-gap-marker--has-gap {
76
+ border-top: 1px dashed rgba(234, 179, 8, 0.5);
77
+ border-bottom: 1px dashed rgba(234, 179, 8, 0.5);
78
+ }
79
+ .section-gap-marker__part {
80
+ position: absolute;
81
+ left: 0;
82
+ width: 100%;
83
+ }
84
+ .section-gap-marker__part--bottom {
85
+ background: rgba(234, 179, 8, 0.15);
86
+ border-bottom: 1px solid rgba(234, 179, 8, 0.4);
87
+ }
88
+ .section-gap-marker__part--top {
89
+ background: rgba(251, 146, 60, 0.15);
90
+ border-bottom: 1px solid rgba(251, 146, 60, 0.4);
91
+ }
92
+ .section-gap-marker__label {
93
+ position: absolute;
94
+ top: 50%;
95
+ left: 50%;
96
+ transform: translate(-50%, -50%);
97
+ background: rgba(234, 179, 8, 0.95);
98
+ color: #1a1a1a;
99
+ font-size: 11px;
100
+ font-family: monospace;
101
+ font-weight: 600;
102
+ padding: 2px 8px;
103
+ border-radius: 3px;
104
+ white-space: nowrap;
105
+ z-index: 1;
106
+ }
107
+ #${TOAST_ID} {
108
+ position: fixed;
109
+ bottom: 20px;
110
+ left: 50%;
111
+ transform: translateX(-50%) translateY(100px);
112
+ background: #1A1A2E;
113
+ color: white;
114
+ font-size: 13px;
115
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
116
+ padding: 10px 20px;
117
+ border-radius: 6px;
118
+ z-index: 100000;
119
+ pointer-events: none;
120
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
121
+ opacity: 0;
122
+ transition: transform 0.3s ease, opacity 0.3s ease;
123
+ white-space: nowrap;
124
+ }
125
+ #${TOAST_ID}.visible {
126
+ opacity: 1;
127
+ transform: translateX(-50%) translateY(0);
128
+ }
129
+ #${TOAST_ID} .toast-status { font-weight: 600; }
130
+ #${TOAST_ID} .toast-status--on { color: #4CAF50; }
131
+ #${TOAST_ID} .toast-status--off { color: #F44336; }
132
+ `;
133
+ document.head.appendChild(style);
134
+ }
135
+
136
+ // --- Toast ---
137
+ let toastTimeout = null;
138
+ function showToast(label, on) {
139
+ injectStyles();
140
+ let toast = document.getElementById(TOAST_ID);
141
+ if (!toast) {
142
+ toast = document.createElement('div');
143
+ toast.id = TOAST_ID;
144
+ document.body.appendChild(toast);
145
+ }
146
+ const cls = on ? 'toast-status--on' : 'toast-status--off';
147
+ toast.innerHTML = `${label}: <span class="toast-status ${cls}">${on ? 'ON' : 'OFF'}</span>`;
148
+ if (toastTimeout) clearTimeout(toastTimeout);
149
+ requestAnimationFrame(() => toast.classList.add('visible'));
150
+ toastTimeout = setTimeout(() => toast.classList.remove('visible'), 2000);
151
+ }
152
+
153
+ // --- Column grid ---
154
+ let colResizeObserver = null;
155
+
156
+ function updateColOverlayHeight() {
157
+ if (!colOverlay) return;
158
+ const container = getContainer();
159
+ colOverlay.style.height = container.scrollHeight + 'px';
160
+ }
161
+
162
+ function createColOverlay() {
163
+ if (colOverlay) return;
164
+ colOverlay = document.createElement('div');
165
+ colOverlay.id = COL_OVERLAY_ID;
166
+ for (let i = 0; i < COLUMNS; i++) {
167
+ const col = document.createElement('div');
168
+ col.className = 'grid-overlay__column';
169
+ colOverlay.appendChild(col);
170
+ }
171
+ const container = getContainer();
172
+ container.style.position = 'relative';
173
+ container.appendChild(colOverlay);
174
+ }
175
+
176
+ function enableCol() {
177
+ colEnabled = true;
178
+ injectStyles();
179
+ createColOverlay();
180
+ colOverlay.style.display = 'flex';
181
+ updateColOverlayHeight();
182
+ // Keep height in sync as content resizes
183
+ if (!colResizeObserver) {
184
+ colResizeObserver = new ResizeObserver(updateColOverlayHeight);
185
+ }
186
+ const container = getContainer();
187
+ Array.from(container.children).forEach(child => {
188
+ if (child !== colOverlay) colResizeObserver.observe(child);
189
+ });
190
+ localStorage.setItem(STORAGE_KEY_COL, 'true');
191
+ }
192
+
193
+ function disableCol() {
194
+ colEnabled = false;
195
+ if (colOverlay) colOverlay.style.display = 'none';
196
+ if (colResizeObserver) colResizeObserver.disconnect();
197
+ localStorage.setItem(STORAGE_KEY_COL, 'false');
198
+ }
199
+
200
+ function dispatchToggleEvent() {
201
+ const detail = { colEnabled, spacingEnabled };
202
+ window.dispatchEvent(new CustomEvent('gridOverlayToggled', { detail }));
203
+ // If we're inside the proto-nav iframe, notify the parent so its
204
+ // sidebar checkboxes stay in sync.
205
+ if (window.parent && window.parent !== window) {
206
+ try {
207
+ window.parent.postMessage({ type: 'gridOverlayState', ...detail }, '*');
208
+ } catch (e) { /* cross-origin — ignore */ }
209
+ }
210
+ }
211
+
212
+ function toggleCol() {
213
+ colEnabled ? disableCol() : enableCol();
214
+ showToast('Column Grid', colEnabled);
215
+ dispatchToggleEvent();
216
+ }
217
+
218
+ // --- Section spacing ---
219
+ function clearSpacingMarkers() {
220
+ spacingMarkers.forEach(el => el.remove());
221
+ spacingMarkers = [];
222
+ }
223
+
224
+ function renderSpacingMarkers() {
225
+ clearSpacingMarkers();
226
+
227
+ const main = document.querySelector('main');
228
+ if (!main) return;
229
+
230
+ const sections = Array.from(main.children).filter(el => {
231
+ const s = window.getComputedStyle(el);
232
+ return s.display !== 'none' && s.visibility !== 'hidden';
233
+ });
234
+
235
+ const scrollTop = getScrollTop();
236
+ const container = getContainer();
237
+ container.style.position = 'relative';
238
+
239
+ for (let i = 0; i < sections.length - 1; i++) {
240
+ const rectA = sections[i].getBoundingClientRect();
241
+ const rectB = sections[i + 1].getBoundingClientRect();
242
+ const styleA = window.getComputedStyle(sections[i]);
243
+ const styleB = window.getComputedStyle(sections[i + 1]);
244
+
245
+ const paddingBottomA = parseFloat(styleA.paddingBottom) || 0;
246
+ const paddingTopB = parseFloat(styleB.paddingTop) || 0;
247
+
248
+ // Measure from last content pixel of A to first content pixel of B
249
+ const contentBottomA = Math.round(rectA.bottom + scrollTop - paddingBottomA);
250
+ const contentTopB = Math.round(rectB.top + scrollTop + paddingTopB);
251
+ const space = contentTopB - contentBottomA;
252
+
253
+ if (space < 0) continue; // sections actually overlap in content
254
+
255
+ const marker = document.createElement('div');
256
+ marker.className = 'section-gap-marker section-gap-marker--has-gap';
257
+ marker.style.top = contentBottomA + 'px';
258
+ marker.style.height = Math.max(space, 2) + 'px';
259
+
260
+ // Padding-bottom of section A (yellow)
261
+ if (paddingBottomA > 0) {
262
+ const partBottom = document.createElement('div');
263
+ partBottom.className = 'section-gap-marker__part section-gap-marker__part--bottom';
264
+ partBottom.style.top = '0px';
265
+ partBottom.style.height = paddingBottomA + 'px';
266
+ marker.appendChild(partBottom);
267
+ }
268
+
269
+ // Padding-top of section B (orange)
270
+ if (paddingTopB > 0) {
271
+ const partTop = document.createElement('div');
272
+ partTop.className = 'section-gap-marker__part section-gap-marker__part--top';
273
+ partTop.style.top = (space - paddingTopB) + 'px';
274
+ partTop.style.height = paddingTopB + 'px';
275
+ marker.appendChild(partTop);
276
+ }
277
+
278
+ const label = document.createElement('div');
279
+ label.className = 'section-gap-marker__label';
280
+ label.textContent = Math.round(space) + 'px';
281
+ marker.appendChild(label);
282
+
283
+ container.appendChild(marker);
284
+ spacingMarkers.push(marker);
285
+ }
286
+ }
287
+
288
+ function enableSpacing() {
289
+ spacingEnabled = true;
290
+ injectStyles();
291
+ renderSpacingMarkers();
292
+ const wrapper = document.getElementById('protoSiteWrapper');
293
+ if (wrapper) {
294
+ wrapper.addEventListener('scroll', renderSpacingMarkers);
295
+ } else {
296
+ window.addEventListener('scroll', renderSpacingMarkers);
297
+ }
298
+ window.addEventListener('resize', renderSpacingMarkers);
299
+ localStorage.setItem(STORAGE_KEY_SPACING, 'true');
300
+ }
301
+
302
+ function disableSpacing() {
303
+ spacingEnabled = false;
304
+ clearSpacingMarkers();
305
+ const wrapper = document.getElementById('protoSiteWrapper');
306
+ if (wrapper) {
307
+ wrapper.removeEventListener('scroll', renderSpacingMarkers);
308
+ } else {
309
+ window.removeEventListener('scroll', renderSpacingMarkers);
310
+ }
311
+ window.removeEventListener('resize', renderSpacingMarkers);
312
+ localStorage.setItem(STORAGE_KEY_SPACING, 'false');
313
+ }
314
+
315
+ function toggleSpacing() {
316
+ spacingEnabled ? disableSpacing() : enableSpacing();
317
+ showToast('Section Spacing', spacingEnabled);
318
+ dispatchToggleEvent();
319
+ }
320
+
321
+ // --- Keyboard ---
322
+ document.addEventListener('keydown', function(e) {
323
+ if (e.ctrlKey && e.shiftKey && (e.key === 'G' || e.key === 'g')) {
324
+ e.preventDefault();
325
+ toggleCol();
326
+ }
327
+ if (e.ctrlKey && e.shiftKey && (e.key === 'H' || e.key === 'h')) {
328
+ e.preventDefault();
329
+ toggleSpacing();
330
+ }
331
+ });
332
+
333
+ // --- Global API ---
334
+ window.GridOverlay = {
335
+ toggleCol, enableCol, disableCol, isColEnabled: () => colEnabled,
336
+ toggleSpacing, enableSpacing, disableSpacing, isSpacingEnabled: () => spacingEnabled
337
+ };
338
+
339
+ // --- Parent → iframe control channel ---
340
+ // Proto-nav posts commands so its sidebar checkbox controls the overlay
341
+ // rendered inside the viewport-preview iframe.
342
+ window.addEventListener('message', function(e) {
343
+ const msg = e.data;
344
+ if (!msg || msg.type !== 'gridOverlay') return;
345
+ switch (msg.action) {
346
+ case 'enableCol': if (!colEnabled) enableCol(); break;
347
+ case 'disableCol': if (colEnabled) disableCol(); break;
348
+ case 'enableSpacing': if (!spacingEnabled) enableSpacing(); break;
349
+ case 'disableSpacing': if (spacingEnabled) disableSpacing(); break;
350
+ case 'requestState': /* fall through to post below */ break;
351
+ default: return;
352
+ }
353
+ if (window.parent && window.parent !== window) {
354
+ window.parent.postMessage(
355
+ { type: 'gridOverlayState', colEnabled, spacingEnabled }, '*'
356
+ );
357
+ }
358
+ });
359
+
360
+ // --- Restore state (deferred so proto-nav has time to set up #protoSiteWrapper) ---
361
+ function restoreState() {
362
+ if (localStorage.getItem(STORAGE_KEY_COL) === 'true') enableCol();
363
+ if (localStorage.getItem(STORAGE_KEY_SPACING) === 'true') enableSpacing();
364
+ // Announce state to parent (no-op when not in an iframe)
365
+ if (window.parent && window.parent !== window) {
366
+ window.parent.postMessage(
367
+ { type: 'gridOverlayState', colEnabled, spacingEnabled }, '*'
368
+ );
369
+ }
370
+ }
371
+
372
+ if (document.readyState === 'loading') {
373
+ document.addEventListener('DOMContentLoaded', () => setTimeout(restoreState, 0));
374
+ } else {
375
+ setTimeout(restoreState, 0);
376
+ }
377
+
378
+ console.log('[Grid Overlay] Ready. Ctrl+Shift+G = columns, Ctrl+Shift+H = section spacing.');
379
+ })();