@arbidocs/blocks 0.4.71 → 0.4.73
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/dist/agents/index.cjs +404 -266
- package/dist/agents/index.js +10 -8
- package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
- package/dist/agents/tasks/WorkflowThreadStrip.d.ts +58 -0
- package/dist/agents/tasks/index.d.ts +1 -0
- package/dist/agents/workflows/WorkflowRunner.d.ts +70 -0
- package/dist/agents/workflows/index.d.ts +7 -1
- package/dist/agents/workflows/planSteps.d.ts +28 -0
- package/dist/agents/workflows/run.d.ts +97 -0
- package/dist/agents/workflows/skillMarkdown.d.ts +15 -0
- package/dist/agents/workflows/types.d.ts +109 -0
- package/dist/agents/workflows/useWorkflowPreview.d.ts +14 -0
- package/dist/agents/workflows/useWorkflowView.d.ts +54 -0
- package/dist/agents/workflows/workflow.d.ts +3 -1
- package/dist/calendar/CalendarGrid.d.ts +2 -0
- package/dist/calendar/CalendarList.d.ts +2 -0
- package/dist/calendar/CalendarSettingsForm.d.ts +2 -0
- package/dist/calendar/EventDetails.d.ts +2 -0
- package/dist/calendar/EventEditor.d.ts +2 -0
- package/dist/calendar/MiniMonth.d.ts +2 -0
- package/dist/calendar/RecurrenceEditor.d.ts +13 -0
- package/dist/calendar/RoomFinder.d.ts +2 -0
- package/dist/calendar/SchedulingAssistant.d.ts +2 -0
- package/dist/calendar/ScopeDialog.d.ts +2 -0
- package/dist/calendar/TimeZonePicker.d.ts +2 -0
- package/dist/calendar/colors.d.ts +4 -0
- package/dist/calendar/draft.d.ts +43 -0
- package/dist/calendar/format.d.ts +14 -0
- package/dist/calendar/grid-model.d.ts +24 -0
- package/dist/calendar/index.cjs +4122 -0
- package/dist/calendar/index.cjs.map +1 -0
- package/dist/calendar/index.d.ts +30 -0
- package/dist/calendar/index.js +4043 -0
- package/dist/calendar/index.js.map +1 -0
- package/dist/calendar/labels.d.ts +4 -0
- package/dist/calendar/recurrence-labels.d.ts +22 -0
- package/dist/calendar/recurrence.d.ts +66 -0
- package/dist/calendar/reminders.d.ts +26 -0
- package/dist/calendar/scheduling.d.ts +27 -0
- package/dist/calendar/types.d.ts +605 -0
- package/dist/calendar/ui.d.ts +16 -0
- package/dist/calendar/zone.d.ts +56 -0
- package/dist/chat/index.cjs +123 -123
- package/dist/chat/index.js +3 -3
- package/dist/chunk-2P3T23C7.js +1250 -0
- package/dist/chunk-2P3T23C7.js.map +1 -0
- package/dist/{chunk-XNRGCQPZ.cjs → chunk-3SFFTSOI.cjs} +5 -5
- package/dist/{chunk-XNRGCQPZ.cjs.map → chunk-3SFFTSOI.cjs.map} +1 -1
- package/dist/{chunk-7WM62NMM.cjs → chunk-6OL5S7MJ.cjs} +5 -2
- package/dist/chunk-6OL5S7MJ.cjs.map +1 -0
- package/dist/chunk-7D737FLE.cjs +43 -0
- package/dist/chunk-7D737FLE.cjs.map +1 -0
- package/dist/{chunk-VUEZARW5.cjs → chunk-B3WCKBJ7.cjs} +278 -5
- package/dist/chunk-B3WCKBJ7.cjs.map +1 -0
- package/dist/{chunk-L5UPP2HC.js → chunk-D46ZAPEE.js} +5 -2
- package/dist/chunk-D46ZAPEE.js.map +1 -0
- package/dist/{chunk-LFGJAZ5H.js → chunk-DDF5GPIJ.js} +6 -36
- package/dist/chunk-DDF5GPIJ.js.map +1 -0
- package/dist/chunk-DETZZBG2.cjs +91 -0
- package/dist/chunk-DETZZBG2.cjs.map +1 -0
- package/dist/chunk-EVUEIBNU.js +89 -0
- package/dist/chunk-EVUEIBNU.js.map +1 -0
- package/dist/{chunk-CXWESDIZ.cjs → chunk-F4RUCUXF.cjs} +6 -6
- package/dist/{chunk-CXWESDIZ.cjs.map → chunk-F4RUCUXF.cjs.map} +1 -1
- package/dist/{chunk-DABEWNL2.js → chunk-G5DP27DU.js} +3 -3
- package/dist/{chunk-DABEWNL2.js.map → chunk-G5DP27DU.js.map} +1 -1
- package/dist/{chunk-VZGBCBYB.js → chunk-GJV2G4FC.js} +276 -7
- package/dist/chunk-GJV2G4FC.js.map +1 -0
- package/dist/chunk-GTNUQBXI.cjs +1296 -0
- package/dist/chunk-GTNUQBXI.cjs.map +1 -0
- package/dist/{chunk-7M22KND4.cjs → chunk-IUR565UW.cjs} +303 -530
- package/dist/chunk-IUR565UW.cjs.map +1 -0
- package/dist/{chunk-5DM6VU4L.cjs → chunk-KJ3QEKOJ.cjs} +3 -3
- package/dist/{chunk-5DM6VU4L.cjs.map → chunk-KJ3QEKOJ.cjs.map} +1 -1
- package/dist/{chunk-THO7DZNN.cjs → chunk-MUMH3Z6K.cjs} +20 -15
- package/dist/chunk-MUMH3Z6K.cjs.map +1 -0
- package/dist/{chunk-3TVTG7FK.js → chunk-ORA2XE7U.js} +4 -4
- package/dist/{chunk-3TVTG7FK.js.map → chunk-ORA2XE7U.js.map} +1 -1
- package/dist/{chunk-5HOAOKZL.js → chunk-OYMWV45N.js} +21 -16
- package/dist/chunk-OYMWV45N.js.map +1 -0
- package/dist/{chunk-HLMFU7L2.js → chunk-QDNXEB3T.js} +272 -488
- package/dist/chunk-QDNXEB3T.js.map +1 -0
- package/dist/{chunk-ILGHS6ZV.js → chunk-SB5ZKOYN.js} +3 -3
- package/dist/{chunk-ILGHS6ZV.js.map → chunk-SB5ZKOYN.js.map} +1 -1
- package/dist/{chunk-CPMNAJLF.js → chunk-TX2ZICS7.js} +24 -4
- package/dist/chunk-TX2ZICS7.js.map +1 -0
- package/dist/{chunk-2ZTONLT5.cjs → chunk-ULWRNGGE.cjs} +25 -4
- package/dist/chunk-ULWRNGGE.cjs.map +1 -0
- package/dist/{chunk-BMWZTNZB.js → chunk-VRPRAU3J.js} +3 -3
- package/dist/{chunk-BMWZTNZB.js.map → chunk-VRPRAU3J.js.map} +1 -1
- package/dist/{chunk-LTA2IAQB.cjs → chunk-WOYUXVVQ.cjs} +8 -8
- package/dist/{chunk-LTA2IAQB.cjs.map → chunk-WOYUXVVQ.cjs.map} +1 -1
- package/dist/chunk-XD2M6LIG.js +41 -0
- package/dist/chunk-XD2M6LIG.js.map +1 -0
- package/dist/{chunk-WBDK4PIA.cjs → chunk-Z5VUZ6YD.cjs} +6 -37
- package/dist/chunk-Z5VUZ6YD.cjs.map +1 -0
- package/dist/collaboration/index.cjs +44 -45
- package/dist/collaboration/index.js +2 -3
- package/dist/connect/docx.cjs +2 -2
- package/dist/connect/docx.js +1 -1
- package/dist/connect/index.cjs +370 -48
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +2 -1
- package/dist/connect/index.js +331 -12
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedSettings.d.ts +13 -0
- package/dist/connection/ConnectedWorkflowBuilder.d.ts +44 -0
- package/dist/connection/ConnectedWorkflowRunner.d.ts +27 -0
- package/dist/connection/useWorkflowThread.d.ts +34 -0
- package/dist/document-tools/index.cjs +4 -5
- package/dist/document-tools/index.cjs.map +1 -1
- package/dist/document-tools/index.js +1 -2
- package/dist/document-tools/index.js.map +1 -1
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/import/index.d.ts +0 -1
- package/dist/files/index.cjs +31 -169
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.js +8 -147
- package/dist/files/index.js.map +1 -1
- package/dist/home/index.cjs +21 -20
- package/dist/home/index.cjs.map +1 -1
- package/dist/home/index.js +3 -2
- package/dist/home/index.js.map +1 -1
- package/dist/index.cjs +680 -542
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +15 -13
- package/dist/index.js.map +1 -1
- package/dist/settings/Billing.d.ts +4 -0
- package/dist/settings/IdentityVerification.d.ts +83 -0
- package/dist/settings/PlanBadge.d.ts +2 -2
- package/dist/settings/PlanCard.d.ts +6 -1
- package/dist/settings/ProfileCard.d.ts +5 -1
- package/dist/settings/SubscriptionParts.d.ts +6 -2
- package/dist/settings/index.cjs +128 -95
- package/dist/settings/index.cjs.map +1 -1
- package/dist/settings/index.d.ts +1 -0
- package/dist/settings/index.js +64 -47
- package/dist/settings/index.js.map +1 -1
- package/dist/shell/ActionCluster.d.ts +3 -1
- package/dist/shell/index.cjs +54 -54
- package/dist/shell/index.js +2 -2
- package/dist/studio/index.cjs +6 -6
- package/dist/studio/index.js +4 -4
- package/dist/workflow-canvas/StepInspector.d.ts +46 -0
- package/dist/workflow-canvas/TriggerInspector.d.ts +46 -0
- package/dist/workflow-canvas/WorkflowBuilder.d.ts +55 -0
- package/dist/workflow-canvas/WorkflowCanvas.d.ts +65 -0
- package/dist/workflow-canvas/edit.d.ts +54 -0
- package/dist/workflow-canvas/index.cjs +1609 -0
- package/dist/workflow-canvas/index.cjs.map +1 -0
- package/dist/workflow-canvas/index.d.ts +13 -0
- package/dist/workflow-canvas/index.js +1579 -0
- package/dist/workflow-canvas/index.js.map +1 -0
- package/dist/workflow-canvas/trigger.d.ts +51 -0
- package/dist/workspaces/index.cjs +2 -3
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.js +1 -2
- package/dist/workspaces/index.js.map +1 -1
- package/package.json +41 -12
- package/src/calendar/calendar.css +316 -0
- package/src/workflow-canvas/canvas.css +113 -0
- package/dist/chunk-2ZTONLT5.cjs.map +0 -1
- package/dist/chunk-5HOAOKZL.js.map +0 -1
- package/dist/chunk-7M22KND4.cjs.map +0 -1
- package/dist/chunk-7WM62NMM.cjs.map +0 -1
- package/dist/chunk-CPMNAJLF.js.map +0 -1
- package/dist/chunk-DCDVWPMB.cjs +0 -29
- package/dist/chunk-DCDVWPMB.cjs.map +0 -1
- package/dist/chunk-HLMFU7L2.js.map +0 -1
- package/dist/chunk-L5UPP2HC.js.map +0 -1
- package/dist/chunk-LFGJAZ5H.js.map +0 -1
- package/dist/chunk-THO7DZNN.cjs.map +0 -1
- package/dist/chunk-TJMKFY5P.js +0 -27
- package/dist/chunk-TJMKFY5P.js.map +0 -1
- package/dist/chunk-VUEZARW5.cjs.map +0 -1
- package/dist/chunk-VZGBCBYB.js.map +0 -1
- package/dist/chunk-WBDK4PIA.cjs.map +0 -1
- package/dist/files/import/CalendarImportRow.d.ts +0 -26
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @arbidocs/blocks/calendar.css — theme for the calendar block (FullCalendar v6 on ARBI tokens).
|
|
3
|
+
* Import once from the app stylesheet: `@import '@arbidocs/blocks/calendar.css';`.
|
|
4
|
+
* FullCalendar v6 injects its own structural CSS at runtime; this file only re-skins it through
|
|
5
|
+
* its `--fc-*` variables and styles the block's own event content. Plain CSS on the HSL triplet
|
|
6
|
+
* tokens, so light and dark themes follow automatically.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
.arbi-calendar {
|
|
10
|
+
--fc-border-color: hsl(var(--border));
|
|
11
|
+
--fc-page-bg-color: hsl(var(--background));
|
|
12
|
+
--fc-neutral-bg-color: hsl(var(--muted) / 0.6);
|
|
13
|
+
--fc-neutral-text-color: hsl(var(--muted-foreground));
|
|
14
|
+
--fc-today-bg-color: hsl(var(--primary) / 0.05);
|
|
15
|
+
--fc-now-indicator-color: hsl(var(--destructive));
|
|
16
|
+
--fc-non-business-color: hsl(var(--muted) / 0.55);
|
|
17
|
+
--fc-highlight-color: hsl(var(--primary) / 0.12);
|
|
18
|
+
--fc-list-event-hover-bg-color: hsl(var(--muted));
|
|
19
|
+
--fc-event-selected-overlay-color: hsl(var(--foreground) / 0.12);
|
|
20
|
+
--fc-small-font-size: 0.75rem;
|
|
21
|
+
color: hsl(var(--foreground));
|
|
22
|
+
font-size: 0.8125rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.arbi-calendar .fc {
|
|
26
|
+
height: 100%;
|
|
27
|
+
}
|
|
28
|
+
.arbi-calendar .fc-scrollgrid {
|
|
29
|
+
border-radius: 0.5rem;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
}
|
|
32
|
+
.arbi-calendar .fc a {
|
|
33
|
+
color: inherit;
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
}
|
|
36
|
+
.arbi-calendar .fc .fc-col-header-cell {
|
|
37
|
+
font-weight: 500;
|
|
38
|
+
color: hsl(var(--muted-foreground));
|
|
39
|
+
}
|
|
40
|
+
.arbi-calendar .fc .fc-col-header-cell-cushion {
|
|
41
|
+
padding: 4px 2px;
|
|
42
|
+
}
|
|
43
|
+
.arbi-calendar .fc .fc-timegrid-slot {
|
|
44
|
+
height: 2.5em;
|
|
45
|
+
}
|
|
46
|
+
.arbi-calendar .fc .fc-timegrid-slot-minor {
|
|
47
|
+
border-top-style: dotted;
|
|
48
|
+
}
|
|
49
|
+
.arbi-calendar .fc .fc-timegrid-slot-label,
|
|
50
|
+
.arbi-calendar .fc .fc-timegrid-axis {
|
|
51
|
+
color: hsl(var(--muted-foreground));
|
|
52
|
+
font-size: 0.6875rem;
|
|
53
|
+
}
|
|
54
|
+
.arbi-calendar .fc .fc-timegrid-slot-label-cushion {
|
|
55
|
+
padding: 0 6px;
|
|
56
|
+
}
|
|
57
|
+
.arbi-calendar .fc .fc-daygrid-day-number {
|
|
58
|
+
font-size: 0.75rem;
|
|
59
|
+
padding: 4px 6px;
|
|
60
|
+
}
|
|
61
|
+
.arbi-calendar .fc .fc-day-today .fc-daygrid-day-number {
|
|
62
|
+
background: hsl(var(--primary));
|
|
63
|
+
color: hsl(var(--primary-foreground));
|
|
64
|
+
border-radius: 9999px;
|
|
65
|
+
min-width: 1.5rem;
|
|
66
|
+
text-align: center;
|
|
67
|
+
margin: 2px;
|
|
68
|
+
padding: 2px 6px;
|
|
69
|
+
}
|
|
70
|
+
.arbi-calendar .fc .fc-daygrid-week-number,
|
|
71
|
+
.arbi-calendar .fc .fc-timegrid-axis-cushion {
|
|
72
|
+
color: hsl(var(--muted-foreground));
|
|
73
|
+
background: transparent;
|
|
74
|
+
font-size: 0.6875rem;
|
|
75
|
+
}
|
|
76
|
+
.arbi-calendar .fc .fc-timegrid-now-indicator-line {
|
|
77
|
+
border-width: 2px 0 0;
|
|
78
|
+
}
|
|
79
|
+
.arbi-calendar .fc .fc-list-day-cushion {
|
|
80
|
+
background: hsl(var(--muted) / 0.6);
|
|
81
|
+
}
|
|
82
|
+
.arbi-calendar .fc .fc-multimonth {
|
|
83
|
+
border: 0;
|
|
84
|
+
}
|
|
85
|
+
.arbi-calendar .fc .fc-multimonth-title {
|
|
86
|
+
font-size: 0.9375rem;
|
|
87
|
+
font-weight: 600;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Day header in time grids: weekday over a big day number; today in a primary circle. */
|
|
91
|
+
.arbi-cal-dayhead {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
align-items: center;
|
|
95
|
+
line-height: 1.1;
|
|
96
|
+
}
|
|
97
|
+
.arbi-cal-dayhead-dow {
|
|
98
|
+
font-size: 0.6875rem;
|
|
99
|
+
text-transform: uppercase;
|
|
100
|
+
letter-spacing: 0.04em;
|
|
101
|
+
}
|
|
102
|
+
.arbi-cal-dayhead-num {
|
|
103
|
+
font-size: 1.25rem;
|
|
104
|
+
font-weight: 500;
|
|
105
|
+
color: hsl(var(--foreground));
|
|
106
|
+
min-width: 2rem;
|
|
107
|
+
height: 2rem;
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
border-radius: 9999px;
|
|
112
|
+
}
|
|
113
|
+
.arbi-cal-dayhead-today .arbi-cal-dayhead-dow {
|
|
114
|
+
color: hsl(var(--primary));
|
|
115
|
+
}
|
|
116
|
+
.arbi-cal-dayhead-today .arbi-cal-dayhead-num {
|
|
117
|
+
background: hsl(var(--primary));
|
|
118
|
+
color: hsl(var(--primary-foreground));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Secondary time zone: two label columns in the time axis. */
|
|
122
|
+
.arbi-cal-slot-labels {
|
|
123
|
+
display: flex;
|
|
124
|
+
gap: 0.5rem;
|
|
125
|
+
justify-content: flex-end;
|
|
126
|
+
white-space: nowrap;
|
|
127
|
+
}
|
|
128
|
+
.arbi-cal-slot-secondary {
|
|
129
|
+
color: hsl(var(--muted-foreground) / 0.75);
|
|
130
|
+
min-width: 2.75em;
|
|
131
|
+
text-align: right;
|
|
132
|
+
}
|
|
133
|
+
.arbi-cal-slot-primary {
|
|
134
|
+
min-width: 2.75em;
|
|
135
|
+
text-align: right;
|
|
136
|
+
}
|
|
137
|
+
.arbi-cal-zone-labels {
|
|
138
|
+
font-size: 0.625rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* ── events ─────────────────────────────────────────────────────────────────── */
|
|
142
|
+
|
|
143
|
+
.arbi-calendar .fc .arbi-cal-event {
|
|
144
|
+
border-radius: 4px;
|
|
145
|
+
box-shadow: none;
|
|
146
|
+
background: transparent;
|
|
147
|
+
}
|
|
148
|
+
.arbi-calendar .fc-timegrid-event.arbi-cal-event,
|
|
149
|
+
.arbi-calendar .fc-daygrid-block-event.arbi-cal-event {
|
|
150
|
+
border-width: 0;
|
|
151
|
+
}
|
|
152
|
+
.arbi-calendar .fc .arbi-cal-event .fc-event-main {
|
|
153
|
+
padding: 0;
|
|
154
|
+
color: inherit;
|
|
155
|
+
}
|
|
156
|
+
.arbi-calendar .fc-timegrid-event-harness-inset .fc-timegrid-event {
|
|
157
|
+
box-shadow: 0 0 0 1px hsl(var(--background));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.arbi-cal-event-inner {
|
|
161
|
+
height: 100%;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
padding: 2px 4px;
|
|
164
|
+
border-radius: 4px;
|
|
165
|
+
background: var(--arbi-cal-color);
|
|
166
|
+
color: var(--arbi-cal-fg);
|
|
167
|
+
border-left: 3px solid color-mix(in srgb, var(--arbi-cal-color) 70%, black);
|
|
168
|
+
font-size: 0.75rem;
|
|
169
|
+
line-height: 1.25;
|
|
170
|
+
}
|
|
171
|
+
.arbi-cal-event-line {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: 3px;
|
|
175
|
+
min-width: 0;
|
|
176
|
+
}
|
|
177
|
+
.arbi-cal-title {
|
|
178
|
+
font-weight: 500;
|
|
179
|
+
overflow: hidden;
|
|
180
|
+
text-overflow: ellipsis;
|
|
181
|
+
white-space: nowrap;
|
|
182
|
+
min-width: 0;
|
|
183
|
+
}
|
|
184
|
+
.arbi-cal-time,
|
|
185
|
+
.arbi-cal-location {
|
|
186
|
+
opacity: 0.85;
|
|
187
|
+
font-size: 0.6875rem;
|
|
188
|
+
overflow: hidden;
|
|
189
|
+
text-overflow: ellipsis;
|
|
190
|
+
white-space: nowrap;
|
|
191
|
+
}
|
|
192
|
+
.arbi-cal-location {
|
|
193
|
+
display: inline-flex;
|
|
194
|
+
align-items: center;
|
|
195
|
+
gap: 2px;
|
|
196
|
+
}
|
|
197
|
+
.arbi-cal-icon {
|
|
198
|
+
width: 0.75rem;
|
|
199
|
+
height: 0.75rem;
|
|
200
|
+
flex-shrink: 0;
|
|
201
|
+
opacity: 0.85;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Month view timed events: dot + time + title, no fill. */
|
|
205
|
+
.arbi-cal-dot-item {
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: 4px;
|
|
209
|
+
min-width: 0;
|
|
210
|
+
padding: 0 2px;
|
|
211
|
+
font-size: 0.75rem;
|
|
212
|
+
color: hsl(var(--foreground));
|
|
213
|
+
}
|
|
214
|
+
.arbi-cal-dot {
|
|
215
|
+
width: 0.5rem;
|
|
216
|
+
height: 0.5rem;
|
|
217
|
+
border-radius: 9999px;
|
|
218
|
+
background: var(--arbi-cal-color);
|
|
219
|
+
flex-shrink: 0;
|
|
220
|
+
}
|
|
221
|
+
.arbi-cal-dot-item .arbi-cal-time {
|
|
222
|
+
opacity: 0.7;
|
|
223
|
+
flex-shrink: 0;
|
|
224
|
+
overflow: visible;
|
|
225
|
+
text-overflow: clip;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* Agenda list. */
|
|
229
|
+
.arbi-cal-list-item {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
gap: 6px;
|
|
233
|
+
min-width: 0;
|
|
234
|
+
flex-wrap: wrap;
|
|
235
|
+
}
|
|
236
|
+
.arbi-cal-list-item .arbi-cal-location {
|
|
237
|
+
color: hsl(var(--muted-foreground));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Free: a light tint. */
|
|
241
|
+
.arbi-cal-free .arbi-cal-event-inner {
|
|
242
|
+
background: color-mix(in srgb, var(--arbi-cal-color) 22%, hsl(var(--background)));
|
|
243
|
+
color: hsl(var(--foreground));
|
|
244
|
+
}
|
|
245
|
+
/* Tentative: diagonal stripes. */
|
|
246
|
+
.arbi-cal-tentative .arbi-cal-event-inner {
|
|
247
|
+
background: repeating-linear-gradient(
|
|
248
|
+
135deg,
|
|
249
|
+
color-mix(in srgb, var(--arbi-cal-color) 38%, hsl(var(--background))) 0 6px,
|
|
250
|
+
color-mix(in srgb, var(--arbi-cal-color) 16%, hsl(var(--background))) 6px 12px
|
|
251
|
+
);
|
|
252
|
+
color: hsl(var(--foreground));
|
|
253
|
+
}
|
|
254
|
+
/* Needs a reply: outlined. */
|
|
255
|
+
.arbi-cal-needs-action .arbi-cal-event-inner {
|
|
256
|
+
background: hsl(var(--background));
|
|
257
|
+
color: hsl(var(--foreground));
|
|
258
|
+
border: 1px solid var(--arbi-cal-color);
|
|
259
|
+
border-left-width: 3px;
|
|
260
|
+
}
|
|
261
|
+
/* Declined (only when shown): faded, struck through. */
|
|
262
|
+
.arbi-cal-declined .arbi-cal-event-inner,
|
|
263
|
+
.arbi-cal-declined .arbi-cal-dot-item,
|
|
264
|
+
.arbi-cal-declined .arbi-cal-list-item {
|
|
265
|
+
opacity: 0.5;
|
|
266
|
+
background: color-mix(in srgb, var(--arbi-cal-color) 14%, hsl(var(--background)));
|
|
267
|
+
color: hsl(var(--muted-foreground));
|
|
268
|
+
}
|
|
269
|
+
.arbi-cal-declined .arbi-cal-title,
|
|
270
|
+
.arbi-cal-cancelled .arbi-cal-title {
|
|
271
|
+
text-decoration: line-through;
|
|
272
|
+
}
|
|
273
|
+
.arbi-cal-cancelled .arbi-cal-event-inner {
|
|
274
|
+
opacity: 0.65;
|
|
275
|
+
}
|
|
276
|
+
/* Out of office: hatched with the event colour. */
|
|
277
|
+
.arbi-cal-oof .arbi-cal-event-inner {
|
|
278
|
+
background: repeating-linear-gradient(
|
|
279
|
+
45deg,
|
|
280
|
+
var(--arbi-cal-color) 0 4px,
|
|
281
|
+
color-mix(in srgb, var(--arbi-cal-color) 75%, black) 4px 8px
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
/* Overlays (facts / workflows / tasks): read-only, dashed outline on a muted tint. */
|
|
285
|
+
.arbi-cal-overlay .arbi-cal-event-inner {
|
|
286
|
+
background: color-mix(in srgb, var(--arbi-cal-color) 10%, hsl(var(--muted)));
|
|
287
|
+
color: hsl(var(--foreground));
|
|
288
|
+
border: 1px dashed var(--arbi-cal-color);
|
|
289
|
+
border-left-width: 1px;
|
|
290
|
+
font-style: italic;
|
|
291
|
+
}
|
|
292
|
+
.arbi-calendar .fc .arbi-cal-overlay {
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
}
|
|
295
|
+
/* Restricted (free/busy only). */
|
|
296
|
+
.arbi-cal-restricted .arbi-cal-event-inner {
|
|
297
|
+
background: hsl(var(--muted));
|
|
298
|
+
color: hsl(var(--muted-foreground));
|
|
299
|
+
border-left-color: hsl(var(--muted-foreground) / 0.5);
|
|
300
|
+
}
|
|
301
|
+
.arbi-calendar .fc .fc-event-past .arbi-cal-event-inner {
|
|
302
|
+
filter: saturate(0.75);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Phone layout. */
|
|
306
|
+
.arbi-calendar-narrow .arbi-cal-toolbar {
|
|
307
|
+
gap: 0.25rem;
|
|
308
|
+
}
|
|
309
|
+
.arbi-calendar-narrow .fc .fc-timegrid-slot-label-cushion {
|
|
310
|
+
padding: 0 3px;
|
|
311
|
+
}
|
|
312
|
+
.arbi-calendar-narrow .arbi-cal-dayhead-num {
|
|
313
|
+
font-size: 1rem;
|
|
314
|
+
min-width: 1.75rem;
|
|
315
|
+
height: 1.75rem;
|
|
316
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @arbidocs/blocks/workflow-canvas.css: the workflow builder's canvas. Import it once, next to
|
|
3
|
+
* `blocks.css`, where `@arbidocs/blocks/workflow-canvas` is used. The graph library's structural
|
|
4
|
+
* rules, its surfaces on the theme tokens, and one accent per kind of step (override the
|
|
5
|
+
* `--wf-*` variables to retheme them).
|
|
6
|
+
*/
|
|
7
|
+
@import '@xyflow/react/dist/base.css';
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
--wf-start: 262 83% 58%;
|
|
11
|
+
--wf-form: 217 91% 55%;
|
|
12
|
+
--wf-upload: 173 70% 38%;
|
|
13
|
+
--wf-agent: 280 70% 56%;
|
|
14
|
+
--wf-review: 32 95% 48%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dark {
|
|
18
|
+
--wf-start: 262 85% 72%;
|
|
19
|
+
--wf-form: 217 91% 68%;
|
|
20
|
+
--wf-upload: 173 60% 52%;
|
|
21
|
+
--wf-agent: 280 75% 72%;
|
|
22
|
+
--wf-review: 32 95% 62%;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.react-flow {
|
|
26
|
+
--xy-edge-stroke-default: hsl(var(--muted-foreground) / 0.45);
|
|
27
|
+
--xy-edge-stroke-width-default: 1.5;
|
|
28
|
+
--xy-edge-stroke-selected-default: hsl(var(--primary));
|
|
29
|
+
--xy-connectionline-stroke-default: hsl(var(--primary));
|
|
30
|
+
--xy-background-pattern-dots-color-default: hsl(var(--muted-foreground) / 0.25);
|
|
31
|
+
--xy-controls-button-background-color-default: hsl(var(--card));
|
|
32
|
+
--xy-controls-button-background-color-hover-default: hsl(var(--muted));
|
|
33
|
+
--xy-controls-button-color-default: hsl(var(--foreground));
|
|
34
|
+
--xy-controls-button-border-color-default: hsl(var(--border));
|
|
35
|
+
--xy-minimap-background-color-default: hsl(var(--card));
|
|
36
|
+
--xy-minimap-mask-background-color-default: hsl(var(--muted) / 0.6);
|
|
37
|
+
--xy-minimap-node-background-color-default: hsl(var(--muted-foreground) / 0.35);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* A step's accent: its kind's colour. */
|
|
41
|
+
.wf-kind-start { --wf-accent: var(--wf-start); }
|
|
42
|
+
.wf-kind-form { --wf-accent: var(--wf-form); }
|
|
43
|
+
.wf-kind-upload { --wf-accent: var(--wf-upload); }
|
|
44
|
+
.wf-kind-agent { --wf-accent: var(--wf-agent); }
|
|
45
|
+
.wf-kind-review { --wf-accent: var(--wf-review); }
|
|
46
|
+
|
|
47
|
+
.wf-node {
|
|
48
|
+
position: relative;
|
|
49
|
+
border-radius: 0.75rem;
|
|
50
|
+
border: 1px solid hsl(var(--border));
|
|
51
|
+
background: hsl(var(--card));
|
|
52
|
+
box-shadow: 0 1px 2px hsl(var(--foreground) / 0.06), 0 4px 12px -4px hsl(var(--foreground) / 0.08);
|
|
53
|
+
transition: box-shadow 150ms, border-color 150ms, transform 150ms;
|
|
54
|
+
overflow: visible;
|
|
55
|
+
}
|
|
56
|
+
.wf-node::before {
|
|
57
|
+
content: '';
|
|
58
|
+
position: absolute;
|
|
59
|
+
inset: 0 auto 0 0;
|
|
60
|
+
width: 4px;
|
|
61
|
+
border-radius: 0.75rem 0 0 0.75rem;
|
|
62
|
+
background: hsl(var(--wf-accent));
|
|
63
|
+
}
|
|
64
|
+
.wf-node:hover {
|
|
65
|
+
box-shadow: 0 2px 4px hsl(var(--foreground) / 0.06), 0 10px 24px -8px hsl(var(--foreground) / 0.18);
|
|
66
|
+
}
|
|
67
|
+
.react-flow__node.selected .wf-node {
|
|
68
|
+
border-color: hsl(var(--wf-accent));
|
|
69
|
+
box-shadow: 0 0 0 3px hsl(var(--wf-accent) / 0.22), 0 10px 24px -8px hsl(var(--foreground) / 0.18);
|
|
70
|
+
}
|
|
71
|
+
.wf-badge {
|
|
72
|
+
color: hsl(var(--wf-accent));
|
|
73
|
+
background: hsl(var(--wf-accent) / 0.12);
|
|
74
|
+
}
|
|
75
|
+
.wf-kind-text { color: hsl(var(--wf-accent)); }
|
|
76
|
+
|
|
77
|
+
/* The start: a pill in its own colour. */
|
|
78
|
+
.wf-start {
|
|
79
|
+
border-radius: 9999px;
|
|
80
|
+
border: 1px solid hsl(var(--wf-start) / 0.5);
|
|
81
|
+
background: linear-gradient(135deg, hsl(var(--wf-start) / 0.16), hsl(var(--wf-start) / 0.06));
|
|
82
|
+
}
|
|
83
|
+
.react-flow__node.selected .wf-start {
|
|
84
|
+
box-shadow: 0 0 0 3px hsl(var(--wf-start) / 0.25);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Handles: small, on the accent; the "+" sits beside the outgoing one. */
|
|
88
|
+
.wf-node .react-flow__handle,
|
|
89
|
+
.wf-start .react-flow__handle {
|
|
90
|
+
width: 10px;
|
|
91
|
+
height: 10px;
|
|
92
|
+
border: 2px solid hsl(var(--card));
|
|
93
|
+
background: hsl(var(--wf-accent));
|
|
94
|
+
}
|
|
95
|
+
.wf-add {
|
|
96
|
+
position: absolute;
|
|
97
|
+
top: 50%;
|
|
98
|
+
right: -38px;
|
|
99
|
+
transform: translateY(-50%);
|
|
100
|
+
opacity: 0;
|
|
101
|
+
transition: opacity 120ms;
|
|
102
|
+
}
|
|
103
|
+
.react-flow__node:hover .wf-add,
|
|
104
|
+
.react-flow__node.selected .wf-add,
|
|
105
|
+
.wf-add[data-state='open'] {
|
|
106
|
+
opacity: 1;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.wf-phase-running { border-color: hsl(var(--wf-accent)); }
|
|
110
|
+
.wf-phase-done { background: linear-gradient(0deg, hsl(var(--wf-accent) / 0.06), hsl(var(--wf-accent) / 0.06)), hsl(var(--card)); }
|
|
111
|
+
.wf-phase-failed { border-color: hsl(var(--destructive) / 0.6); }
|
|
112
|
+
.wf-phase-skipped,
|
|
113
|
+
.wf-phase-blocked { opacity: 0.6; }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/settings/ModalScaffold.tsx"],"names":["jsx","DialogHeader","cn","DialogFooter","useRestoreFocus","Dialog","jsxs","DialogContent","DialogTitle","DialogDescription"],"mappings":"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","file":"chunk-2ZTONLT5.cjs","sourcesContent":["import type { ComponentProps, ReactNode, RefObject } from 'react'\nimport {\n cn,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n type DialogPresentation,\n} from '@arbidocs/react/ui'\nimport { useRestoreFocus } from '../lib/useRestoreFocus'\n\n/** Tailwind classes for a modal section heading (also usable on a `Label`). */\nexport const MODAL_SECTION_TITLE_CLASS =\n 'mb-2 flex items-center gap-1 text-sm font-medium text-muted-foreground'\n\n/** Header of a hand-assembled modal: no tinted band, just space. */\nexport function ModalHeader({ className, ...props }: ComponentProps<typeof DialogHeader>) {\n return (\n <DialogHeader\n data-slot=\"modal-header\"\n className={cn('flex-shrink-0 rounded-t-lg bg-transparent p-6 pb-3 pr-12', className)}\n {...props}\n />\n )\n}\n\n/** A padded group inside a modal body. */\nexport function ModalSection({ className, ...props }: ComponentProps<'div'>) {\n return <div data-slot=\"modal-section\" className={cn('pt-4', className)} {...props} />\n}\n\n/** Muted label above the content of a {@link ModalSection}. */\nexport function ModalSectionTitle({ className, ...props }: ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"modal-section-title\"\n className={cn(MODAL_SECTION_TITLE_CLASS, className)}\n {...props}\n />\n )\n}\n\nexport type ModalSize = 'sm' | 'md' | 'lg' | 'xl'\n\nconst SIZE_CLASS: Record<ModalSize, string> = {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-2xl',\n xl: 'sm:max-w-4xl',\n}\n\nexport interface ModalScaffoldProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: ReactNode\n /** Accessible description; visually hidden unless `showDescription`. */\n description?: ReactNode\n showDescription?: boolean\n /** Icon shown before the title. */\n icon?: ReactNode\n size?: ModalSize\n /** Phone presentation; defaults to a bottom sheet for `lg`/`xl`, a centred box otherwise. */\n presentation?: DialogPresentation\n className?: string\n testId?: string\n /**\n * `alertdialog` for a destructive or blocking confirmation: announced as an alert, dismissed\n * only through its own buttons or Escape (not by clicking outside).\n */\n role?: 'dialog' | 'alertdialog'\n /**\n * Block dismissal by outside click AND Escape; only the dialog's own buttons close it. For a\n * dialog that shows a secret once (a new API key). Default false. An `alertdialog` already\n * ignores outside clicks.\n */\n dismissible?: boolean\n /** Called on a pointer/focus interaction outside; `preventDefault()` keeps the dialog open. */\n onInteractOutside?: (event: Event) => void\n /** Called on Escape; `preventDefault()` keeps the dialog open. */\n onEscapeKeyDown?: (event: KeyboardEvent) => void\n /** Element that receives focus when the dialog opens (an alert dialog focuses its safe action). */\n initialFocusRef?: RefObject<HTMLElement | null>\n children?: ReactNode\n}\n\nfunction ModalBody({ className, ...props }: ComponentProps<'div'>) {\n return <div data-slot=\"modal-body\" className={cn('space-y-4', className)} {...props} />\n}\n\n/**\n * Action row. Stacked full-width on phones (primary action on top), right-aligned on wider\n * screens. Sticks to the bottom of the scrolling dialog body so the actions stay reachable.\n */\nfunction ModalFooter({ className, ...props }: ComponentProps<typeof DialogFooter>) {\n return (\n <DialogFooter\n data-slot=\"modal-footer\"\n className={cn(\n 'sticky bottom-0 -mx-6 -mb-6 mt-4 border-t border-border bg-background px-6 py-3',\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * Standard dialog: icon + title + description header, then the compound\n * `ModalScaffold.Body` / `ModalScaffold.Footer` slots.\n */\nexport function ModalScaffold({\n open,\n onOpenChange,\n title,\n description,\n showDescription = false,\n icon,\n size = 'md',\n presentation,\n className,\n testId,\n role = 'dialog',\n initialFocusRef,\n dismissible = true,\n onInteractOutside,\n onEscapeKeyDown,\n children,\n}: ModalScaffoldProps) {\n const restoreFocus = useRestoreFocus()\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n role={role}\n presentation={presentation ?? (size === 'lg' || size === 'xl' ? 'sheet' : 'center')}\n className={cn(SIZE_CLASS[size], 'flex flex-col gap-0 overflow-hidden p-0', className)}\n data-testid={testId}\n onInteractOutside={(e) => {\n if (role === 'alertdialog' || !dismissible) e.preventDefault()\n onInteractOutside?.(e)\n }}\n onEscapeKeyDown={(e) => {\n if (!dismissible) e.preventDefault()\n onEscapeKeyDown?.(e)\n }}\n onOpenAutoFocus={(e) => {\n restoreFocus.onOpenAutoFocus(e)\n if (initialFocusRef?.current) {\n e.preventDefault()\n initialFocusRef.current.focus()\n }\n }}\n onCloseAutoFocus={restoreFocus.onCloseAutoFocus}\n >\n <ModalHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n {icon}\n {title}\n </DialogTitle>\n <DialogDescription className={showDescription ? undefined : 'sr-only'}>\n {description ?? title}\n </DialogDescription>\n </ModalHeader>\n <div\n data-slot=\"modal-scroll\"\n className=\"min-h-0 flex-1 space-y-4 overflow-y-auto overscroll-contain px-6 pb-6\"\n >\n {children}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\nModalScaffold.Body = ModalBody\nModalScaffold.Footer = ModalFooter\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":[],"mappings":"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","file":"chunk-5HOAOKZL.js","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { useArbi, type LoginProfile } from '@arbidocs/react'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n /**\n * The deployment domain the user's keys are derived for (`arbi.getDeploymentDomain()`), for the\n * document tools' e-signing. `undefined` in demo mode.\n */\n deploymentDomain: string | undefined\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /** Fallback workspace ext_id when none is actively selected. */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst sessionUserKey = (apiUrl: string) => `arbi:sessionUser:${apiUrl}`\nfunction rememberSessionUser(apiUrl: string, email: string | null) {\n try {\n if (email) window.localStorage.setItem(sessionUserKey(apiUrl), normalizeUserKey(email))\n else window.localStorage.removeItem(sessionUserKey(apiUrl))\n } catch {\n /* Storage may be unavailable. */\n }\n}\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const [workspaceId, setWorkspaceId] = useState<string | null>(null)\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n rememberSessionUser(config.apiUrl, null)\n storageUserRef.current = null\n setUser(null)\n setWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, config.apiUrl]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n setWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId])\n\n const login = useCallback(\n async (email: string, password: string, restoring = false) => {\n setError(null)\n // No backend configured → run the seeded demo workspace.\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n if (restoring) {\n if (!(await arbi.restoreSession(email))) {\n rememberSessionUser(config.apiUrl, null)\n setStatus('disconnected')\n return\n }\n } else await arbi.login(email, password)\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n workspaces[0]\n await arbi.selectWorkspace(target.external_id)\n setWorkspaceId(target.external_id)\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n setUser(resolved)\n rememberSessionUser(config.apiUrl, email)\n setStatus('authenticated')\n } catch (e) {\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]\n )\n\n // Run once even under StrictMode; passwords and signing keys are never stored here.\n const recoveryStarted = useRef(false)\n useEffect(() => {\n if (recoveryStarted.current || !isLiveConfigured) return\n recoveryStarted.current = true\n let email: string | null = null\n try {\n email = window.localStorage.getItem(sessionUserKey(config.apiUrl))\n } catch {\n /* unavailable */\n }\n if (email) void login(email, '', true)\n else setStatus('disconnected')\n }, [isLiveConfigured, config.apiUrl, login])\n\n const logout = useCallback(() => {\n rememberSessionUser(config.apiUrl, null)\n if (mode === 'live') {\n void arbi.logout?.()\n }\n setUser(null)\n setWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n }, [arbi, mode, config.apiUrl])\n\n // Affirmative selection: open the workspace on the server (live), then remember\n // it in state + storage so every surface — and the next login — is in sync.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n await arbi.selectWorkspace(id)\n }\n setWorkspaceId(id)\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped\n // it. Idempotent: re-running `/open` for the already-selected workspace is safe.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n const id =\n workspaceId ??\n readPersistedWorkspace(config.apiUrl, storageUserRef.current) ??\n config.workspaceId\n if (id) await arbi.selectWorkspace(id)\n }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n deploymentDomain: isLiveConfigured ? arbi.getDeploymentDomain() : undefined,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n arbi,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n return <ConnectionContext.Provider value={value}>{children}</ConnectionContext.Provider>\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection must be used within ConnectionProvider')\n return ctx\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n"]}
|