@arbidocs/blocks 0.3.110

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.
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@arbidocs/blocks",
3
+ "version": "0.3.110",
4
+ "description": "Composable AI-native back-office blocks on top of @arbidocs/react — prompt library, theme system, shell, builders and vertical primitives.",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./studio.css": "./src/studio/studio.css",
16
+ "./grid.css": "./src/components/grid.css"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src/studio/studio.css",
21
+ "src/components/grid.css"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "test": "vitest run",
26
+ "test:watch": "vitest",
27
+ "typecheck": "tsc --noEmit"
28
+ },
29
+ "dependencies": {
30
+ "@arbidocs/react": "0.3.110",
31
+ "@arbidocs/sdk": "0.3.110",
32
+ "ag-grid-community": "^35.3.0",
33
+ "ag-grid-react": "^35.3.0",
34
+ "class-variance-authority": "^0.7.1",
35
+ "clsx": "^2.1.1",
36
+ "lucide-react": "^1.22.0",
37
+ "tailwind-merge": "^3.6.0",
38
+ "zustand": "^5.0.14"
39
+ },
40
+ "peerDependencies": {
41
+ "@measured/puck": ">=0.20",
42
+ "@tanstack/react-query": ">=5",
43
+ "react": ">=18",
44
+ "react-dom": ">=18",
45
+ "react-router-dom": ">=6"
46
+ },
47
+ "devDependencies": {
48
+ "@measured/puck": "^0.20.2",
49
+ "@tanstack/react-query": "^5.101.2",
50
+ "@testing-library/react": "^16.3.0",
51
+ "@types/react": "^19.2.17",
52
+ "@types/react-dom": "^19.2.2",
53
+ "jsdom": "^29.1.1",
54
+ "react": "^19.2.7",
55
+ "react-dom": "^19.2.7",
56
+ "react-router-dom": "^6.30.1",
57
+ "vitest": "^4.0.18"
58
+ },
59
+ "license": "MIT",
60
+ "publishConfig": {
61
+ "access": "public"
62
+ },
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "git+https://github.com/arbicity/ARBI-frontend.git",
66
+ "directory": "packages/arbi-blocks"
67
+ },
68
+ "keywords": [
69
+ "arbi",
70
+ "blocks",
71
+ "composable",
72
+ "vertical",
73
+ "react"
74
+ ]
75
+ }
@@ -0,0 +1,365 @@
1
+ /**
2
+ * AG Grid Theme Overrides
3
+ * Uses CSS custom properties to integrate with our theme system
4
+ * This enables dark mode support and consistent theming
5
+ *
6
+ * AG Grid v34 CSS variable reference:
7
+ * https://www.ag-grid.com/javascript-data-grid/theming-parameters/
8
+ */
9
+
10
+ @layer components {
11
+ :root {
12
+ /* Core colors - reference our theme variables */
13
+ --ag-background-color: hsl(var(--background));
14
+ --ag-foreground-color: hsl(var(--foreground));
15
+ --ag-border-color: hsl(var(--border));
16
+
17
+ /* Header styling */
18
+ --ag-header-background-color: hsl(var(--muted));
19
+ --ag-header-foreground-color: hsl(var(--muted-foreground));
20
+
21
+ /* Row styling */
22
+ --ag-odd-row-background-color: hsl(var(--background));
23
+ /* Hover tint: a neutral foreground-based overlay (not --muted, which sits
24
+ too close to the background to track) — subtle but clearly shows which
25
+ row the pointer is on. Pure CSS variable, zero per-row cost. */
26
+ --ag-row-hover-color: hsl(var(--foreground) / 0.05);
27
+
28
+ /* Selection - use secondary color with low opacity */
29
+ --ag-selected-row-background-color: hsl(var(--secondary) / 0.1);
30
+ --ag-range-selection-background-color: hsl(var(--secondary) / 0.1);
31
+
32
+ /* Accent color for checkboxes, focus rings, etc */
33
+ --ag-accent-color: hsl(var(--secondary));
34
+
35
+ /* Input styling */
36
+ --ag-input-focus-border-color: hsl(var(--secondary));
37
+
38
+ /* Cell borders - match background for invisible borders */
39
+ --ag-cell-horizontal-border: transparent;
40
+ }
41
+
42
+ .dark {
43
+ /* Dark mode overrides - CSS variables automatically cascade */
44
+ --ag-row-hover-color: hsl(var(--foreground) / 0.07);
45
+ --ag-selected-row-background-color: hsl(var(--secondary) / 0.2);
46
+ }
47
+ }
48
+
49
+ /* Private (un-shared) documents: render the row selection checkbox in primary
50
+ navy instead of the secondary cyan accent — matching the document
51
+ shared/private colour convention. Scoped to the checkbox wrapper so nothing
52
+ else in the row (selected-row tint, focus ring) shifts. The `doc-row-private`
53
+ class comes from the Documents grid's rowClassRules (a pure data predicate,
54
+ so no per-row latency). */
55
+ .ag-row.doc-row-private .ag-checkbox-input-wrapper {
56
+ --ag-accent-color: hsl(var(--primary));
57
+ }
58
+
59
+ /* The unified Document column's ⋯ kebab is hover-only (revealed when the row is
60
+ hovered) so it doesn't clutter the table at rest. Uses native :hover on the
61
+ row (reliable regardless of AG Grid's JS hover class). It also stays visible
62
+ while its menu is open (handled by the button's data-[state=open] class). */
63
+ .ag-row:hover .doc-row-kebab,
64
+ .ag-row-hover .doc-row-kebab {
65
+ opacity: 1;
66
+ }
67
+
68
+ /* Row hover affordance: a subtle left accent bar so the active row reads as
69
+ actionable (mirrors Google Drive's list-row hover). Pure CSS on the row's
70
+ hover state — no per-row JS, so the million-doc grid is unaffected. */
71
+ .ag-row:hover,
72
+ .ag-row-hover {
73
+ box-shadow: inset 2px 0 0 hsl(var(--secondary));
74
+ }
75
+
76
+ /* Stronger header/body separation. The header is already shaded via
77
+ --ag-header-background-color; a hairline under the band sharpens the
78
+ boundary the way Notion's header row does. */
79
+ .ag-header {
80
+ border-bottom: 1px solid hsl(var(--border));
81
+ }
82
+
83
+ /* Numeric columns (Pages, Size): right-align + tabular figures so digits line
84
+ up column-wise and are faster to compare. */
85
+ .cell-numeric {
86
+ text-align: right;
87
+ font-variant-numeric: tabular-nums;
88
+ }
89
+
90
+ /* Icon columns (e.g. Status): horizontally center the lone glyph. text-align
91
+ covers the default (inline) cell; justify-content covers the flex cell used
92
+ by height-adjustable grids (.ag-cells-centered). */
93
+ .cell-hcenter {
94
+ text-align: center;
95
+ justify-content: center;
96
+ }
97
+
98
+ /* Center the matching header label so it sits above the centered icon. */
99
+ .header-hcenter .ag-header-cell-label {
100
+ justify-content: center;
101
+ }
102
+
103
+ /* Date column: tabular figures (kept left-aligned) so YYYY-MM-DD values align. */
104
+ .cell-tnum {
105
+ font-variant-numeric: tabular-nums;
106
+ }
107
+
108
+ /* Vertically center every cell's content (height-adjustable grids only, flagged
109
+ by .ag-cells-centered on the wrapper). As rows grow tall to fit multi-line
110
+ text, a single line or a lone entity pill sits in the middle of the row and
111
+ multi-line text is balanced top-to-bottom — the classic, tidy grid look at
112
+ any row height. */
113
+ .ag-cells-centered .ag-cell {
114
+ display: flex;
115
+ align-items: center;
116
+ /* AG Grid lays every cell out as `position: absolute; height: 100%` with no
117
+ explicit `top`. In this grid the absolute cell's static position resolves to
118
+ the BOTTOM of the row, so cells (and their content) drop to the row's bottom
119
+ edge and spill into the row beneath — content appears in a row that
120
+ shouldn't exist; on the last row it shows as misaligned/empty cells because
121
+ there is no row below to cover the overflow. Pin every cell to its row's
122
+ top. (position: relative cells, e.g. .cell-select-editable, already sit at
123
+ the top, so this is a no-op for them.) */
124
+ top: 0;
125
+ /* Vertical breathing room so content (and multi-line Abstract text) doesn't
126
+ crowd the row hairlines above and below. */
127
+ padding-top: 8px;
128
+ padding-bottom: 8px;
129
+ }
130
+
131
+ /* Status: the progress-bar + label renderer needs the full row height. The
132
+ default 8px top/bottom cell padding leaves almost no room at the minimum row
133
+ height (so the bar/label get clipped), so trim it and pin the content to the
134
+ top of the cell. */
135
+ .cell-status.ag-cell {
136
+ padding-top: 1px;
137
+ padding-bottom: 1px;
138
+ align-items: flex-start;
139
+ }
140
+
141
+ /* Abstract: height-driven multi-line text. The text wraps and the row height
142
+ decides how many lines show — so the density slider doubles as "how much
143
+ abstract do I want to see" (one line when compact, several when tall). It
144
+ reads from the FIRST line down and clamps to a WHOLE number of lines
145
+ (--abstract-line-clamp, computed from the row height in GridView) so there is
146
+ never a sliced half-line against the top or bottom hairline — the cut lands
147
+ on a line boundary with an ellipsis. The value renders directly on the cell
148
+ (it is itself .ag-cell-value), so we target the cell. Only affects the
149
+ non-editing display (editing opens the large-text popup editor). */
150
+ .cell-abstract.ag-cell {
151
+ display: block;
152
+ white-space: normal;
153
+ overflow: hidden;
154
+ line-height: 1.35;
155
+ /* Snap the box to a WHOLE number of text lines so the overflow clip always
156
+ lands on a line boundary — never mid-line (which reads as a half-line
157
+ "bleeding" into the next row). Both values are computed from the row height
158
+ once in GridView (zero per-row cost): --abstract-pad-y shrinks on short
159
+ rows so a line always fits, and --abstract-max-h caps the box at exactly N
160
+ lines + padding + border. Fallbacks cover grids without a density control. */
161
+ padding-top: var(--abstract-pad-y, 8px);
162
+ padding-bottom: var(--abstract-pad-y, 8px);
163
+ max-height: var(--abstract-max-h, calc(2 * 1.35em + 18px));
164
+ }
165
+
166
+ /* AG Grid structural customizations (not theme colors) */
167
+ .ag-header-cell-text {
168
+ order: 2;
169
+ }
170
+
171
+ .ag-header-icon {
172
+ order: 1;
173
+ margin-right: 8px;
174
+ margin-left: 0;
175
+ margin-top: 4px;
176
+ }
177
+
178
+ .ag-header-cell-label {
179
+ display: flex;
180
+ align-items: center !important;
181
+ }
182
+
183
+ /* White dividers between header columns - use theme variable */
184
+ .ag-header-cell:not(:last-child)::after {
185
+ content: '';
186
+ position: absolute;
187
+ right: 0;
188
+ top: 0;
189
+ bottom: 0;
190
+ width: 1px;
191
+ background-color: hsl(var(--background));
192
+ pointer-events: none;
193
+ }
194
+
195
+ /* Hide column borders on cells */
196
+ .ag-cell {
197
+ border-right-color: transparent !important;
198
+ /* Allow users to select / copy cell text even in read-only cells.
199
+ AG Grid defaults to user-select: none and only opts cells in via
200
+ enableCellTextSelection (which we avoid to keep mouse handling
201
+ untouched for the million-doc grid). Editable cells enter edit
202
+ mode on single click, so this only takes effect on cells the user
203
+ can't edit — file name, dates, hashes, and metadata fields when
204
+ the viewer lacks write permissions. */
205
+ -webkit-user-select: text;
206
+ user-select: text;
207
+ }
208
+
209
+ /* Make custom headers sortable by making the title area clickable */
210
+ .custom-header-title {
211
+ cursor: pointer;
212
+ user-select: none;
213
+ }
214
+
215
+ .custom-header-title:hover {
216
+ background-color: hsl(var(--muted-foreground) / 0.05);
217
+ }
218
+
219
+ /* Horizontal scrollbar sits at the bottom of the grid, above the bulk-actions bar.
220
+ .ag-body-horizontal-scroll is a direct flex child of .ag-root (flex column); order:100
221
+ pushes it below .ag-body which appears first in the DOM. */
222
+ .ag-root {
223
+ display: flex !important;
224
+ flex-direction: column !important;
225
+ }
226
+
227
+ .ag-body-horizontal-scroll {
228
+ order: 100 !important;
229
+ height: 8px !important;
230
+ min-height: 8px !important;
231
+ max-height: 8px !important;
232
+ }
233
+
234
+ .ag-body-horizontal-scroll-viewport,
235
+ .ag-body-horizontal-scroll-container {
236
+ height: 8px !important;
237
+ min-height: 8px !important;
238
+ max-height: 8px !important;
239
+ }
240
+
241
+ /* Hide the scrollbar when not scrollable (AG Grid adds inline style) */
242
+ .ag-body-horizontal-scroll.ag-scrollbar-invisible {
243
+ display: none !important;
244
+ }
245
+
246
+ /* Custom scrollbar styling (webkit browsers) */
247
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar {
248
+ height: 8px;
249
+ }
250
+
251
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-track {
252
+ background: hsl(var(--muted));
253
+ }
254
+
255
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb {
256
+ background: hsl(var(--muted-foreground) / 0.3);
257
+ border-radius: 3px;
258
+ }
259
+
260
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb:hover {
261
+ background: hsl(var(--muted-foreground) / 0.5);
262
+ }
263
+
264
+ /* Arrow buttons: one left arrow at the left end, one right arrow at the right end.
265
+ Webkit exposes two slots per direction (:start and :end); hide the unused ones. */
266
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:decrement:end,
267
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:increment:start {
268
+ display: none;
269
+ }
270
+
271
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:decrement:start {
272
+ display: block;
273
+ width: 18px;
274
+ height: 8px;
275
+ background: hsl(var(--muted)) no-repeat center / 7px 7px;
276
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M6.5 2L3.5 5l3 3' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
277
+ }
278
+
279
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:decrement:start:hover {
280
+ background-color: hsl(var(--muted-foreground) / 0.15);
281
+ }
282
+
283
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:increment:end {
284
+ display: block;
285
+ width: 18px;
286
+ height: 8px;
287
+ background: hsl(var(--muted)) no-repeat center / 7px 7px;
288
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M3.5 2L6.5 5l-3 3' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
289
+ }
290
+
291
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-button:horizontal:increment:end:hover {
292
+ background-color: hsl(var(--muted-foreground) / 0.15);
293
+ }
294
+
295
+ /* Vertical scrollbar styling - match horizontal for consistency */
296
+ .ag-body-vertical-scroll {
297
+ width: 8px !important;
298
+ min-width: 8px !important;
299
+ max-width: 8px !important;
300
+ }
301
+
302
+ .ag-body-vertical-scroll-viewport,
303
+ .ag-body-vertical-scroll-container {
304
+ width: 8px !important;
305
+ min-width: 8px !important;
306
+ max-width: 8px !important;
307
+ }
308
+
309
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar {
310
+ width: 8px;
311
+ }
312
+
313
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-track {
314
+ background: hsl(var(--muted));
315
+ }
316
+
317
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-thumb {
318
+ background: hsl(var(--muted-foreground) / 0.3);
319
+ border-radius: 3px;
320
+ }
321
+
322
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-thumb:hover {
323
+ background: hsl(var(--muted-foreground) / 0.5);
324
+ }
325
+
326
+ /* Arrow buttons: one up arrow at the top, one down arrow at the bottom */
327
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:decrement:end,
328
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:increment:start {
329
+ display: none;
330
+ }
331
+
332
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:decrement:start {
333
+ display: block;
334
+ width: 8px;
335
+ height: 18px;
336
+ background: hsl(var(--muted)) no-repeat center / 10px 10px;
337
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2 6.5L5 3.5l3 3' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
338
+ }
339
+
340
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:decrement:start:hover {
341
+ background-color: hsl(var(--muted-foreground) / 0.15);
342
+ }
343
+
344
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:increment:end {
345
+ display: block;
346
+ width: 8px;
347
+ height: 18px;
348
+ background: hsl(var(--muted)) no-repeat center / 10px 10px;
349
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M2 3.5L5 6.5l3-3' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");
350
+ }
351
+
352
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-button:vertical:increment:end:hover {
353
+ background-color: hsl(var(--muted-foreground) / 0.15);
354
+ }
355
+
356
+ /* Scrollbar corner where horizontal and vertical meet */
357
+ .ag-body-horizontal-scroll-viewport::-webkit-scrollbar-corner,
358
+ .ag-body-vertical-scroll-viewport::-webkit-scrollbar-corner {
359
+ background: hsl(var(--muted));
360
+ }
361
+
362
+ /* AG Grid's horizontal scrollbar right spacer (corner piece) */
363
+ .ag-horizontal-right-spacer {
364
+ background: hsl(var(--muted)) !important;
365
+ }
@@ -0,0 +1,70 @@
1
+ /* Puck editor chrome + studio layout. Scoped to the studio routes so it never
2
+ * leaks into the marketing site or back-office. We import Puck's own CSS here
3
+ * (studio-owned CSS) rather than in the app's global stylesheet. */
4
+ @import "@measured/puck/puck.css";
5
+
6
+ /* Keep the Puck canvas on a warm surface so previews read true, and repaint
7
+ * Puck's default azure accent as emerald so the editor chrome matches a sensible
8
+ * brand default (buttons, selected outlines, focus rings). The scale keeps
9
+ * Puck's light→dark ordering so contrast stays legible. */
10
+ .al-studio {
11
+ --puck-color-grey-01: var(--color-ink);
12
+ --puck-color-azure-01: #052a20;
13
+ --puck-color-azure-02: #083a2c;
14
+ --puck-color-azure-03: #0b4a39;
15
+ --puck-color-azure-04: #0f5a46; /* brand emerald — primary actions */
16
+ --puck-color-azure-05: #1f7d61; /* primary hover/active */
17
+ --puck-color-azure-06: #4f9d84;
18
+ --puck-color-azure-07: #79b6a3;
19
+ --puck-color-azure-08: #a6cdc0;
20
+ --puck-color-azure-09: #cbe3d9;
21
+ --puck-color-azure-10: #e2ede8; /* emerald-soft */
22
+ --puck-color-azure-11: #eef5f1;
23
+ --puck-color-azure-12: #f5faf7;
24
+ height: 100vh;
25
+ display: flex;
26
+ flex-direction: column;
27
+ }
28
+
29
+ .al-studio__puck {
30
+ flex: 1;
31
+ min-height: 0;
32
+ }
33
+
34
+ /* The small AI-write control that rides alongside text fields. */
35
+ .al-ai-field {
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 0.4rem;
39
+ }
40
+ .al-ai-field__input {
41
+ width: 100%;
42
+ border: 1px solid var(--color-border);
43
+ border-radius: 0.4rem;
44
+ padding: 0.5rem 0.6rem;
45
+ font: inherit;
46
+ background: var(--color-card);
47
+ color: var(--color-foreground);
48
+ }
49
+ .al-ai-field__input:focus {
50
+ outline: 2px solid var(--color-emerald);
51
+ outline-offset: 1px;
52
+ }
53
+ .al-ai-field__btn {
54
+ align-self: flex-start;
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: 0.35rem;
58
+ font-size: 0.75rem;
59
+ font-weight: 600;
60
+ color: var(--color-ai-accent);
61
+ background: var(--color-ai-accent-soft);
62
+ border: 1px solid transparent;
63
+ border-radius: 999px;
64
+ padding: 0.2rem 0.6rem;
65
+ cursor: pointer;
66
+ }
67
+ .al-ai-field__btn:disabled {
68
+ opacity: 0.6;
69
+ cursor: default;
70
+ }