@meetreeve/ui 0.14.0 → 0.16.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.
- package/README.md +41 -0
- package/dist/index.d.mts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +53 -9
- package/dist/index.mjs +52 -9
- package/dist/stage-rail/index.d.mts +173 -0
- package/dist/stage-rail/index.d.ts +173 -0
- package/dist/stage-rail/index.js +3814 -0
- package/dist/stage-rail/index.mjs +3783 -0
- package/dist/tokens/index.d.mts +12 -1
- package/dist/tokens/index.d.ts +12 -1
- package/dist/tokens/index.js +8 -0
- package/dist/tokens/index.mjs +7 -0
- package/dist/tokens.css +5 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -187,6 +187,47 @@ the host must define `--color-popover`, `--color-popover-foreground`,
|
|
|
187
187
|
`--color-border` and `--color-ring`, and Tailwind consumers must include this
|
|
188
188
|
package's `dist` as a `@source` (see ResponsiveHeader above).
|
|
189
189
|
|
|
190
|
+
## StageRail (DEV-13855)
|
|
191
|
+
|
|
192
|
+
Domain-free "flow of cards": cards joined by connectors, left to right.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { StageRail, StageCardShell, StageConnector, StageRailMini } from "@meetreeve/ui/stage-rail";
|
|
196
|
+
|
|
197
|
+
<StageRail
|
|
198
|
+
stages={steps}
|
|
199
|
+
getId={(s) => s.id}
|
|
200
|
+
leading={<TriggerCard />} // fixed: never reorders, nothing inserts before it
|
|
201
|
+
trailing={<ExitCard />} // fixed: nothing inserts after it
|
|
202
|
+
selectedId={selected}
|
|
203
|
+
onSelect={setSelected}
|
|
204
|
+
onInsertAt={(i) => insertStep(i)}
|
|
205
|
+
reorderable
|
|
206
|
+
onReorder={(from, to) => moveStep(from, to)}
|
|
207
|
+
editable={isDraft} // false: no +, no reorder
|
|
208
|
+
ruler={[{ label: "Start" }, ...steps.map((s) => ({ label: s.day })), { label: "End" }]}
|
|
209
|
+
renderCard={(s, i, ctx) => (
|
|
210
|
+
<StageCardShell selected={ctx.selected} dragging={ctx.dragging} dragHandle={ctx.reorderable}
|
|
211
|
+
onSelect={ctx.select} index={i + 1} className="w-64">
|
|
212
|
+
…
|
|
213
|
+
</StageCardShell>
|
|
214
|
+
)}
|
|
215
|
+
renderConnector={(prev, next, i, ctx) => ( // prev/next null = a fixed slot
|
|
216
|
+
<StageConnector label="2 days" onInsert={ctx.canInsert ? ctx.insert : undefined} dropActive={ctx.dropActive} />
|
|
217
|
+
)}
|
|
218
|
+
/>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
- Reorder is opt-in and starts only from a `[data-stage-drag-handle]` (the
|
|
222
|
+
shell's `dragHandle`), so inputs and buttons in cards and connectors never
|
|
223
|
+
start a drag. Clicks and keys from interactive descendants never select.
|
|
224
|
+
- Styling uses the consumer's shadcn theme tokens (`bg-card`, `ring-primary`,
|
|
225
|
+
`ring-destructive`, `text-muted-foreground`, …), so light and dark follow the
|
|
226
|
+
host. Spacing reads `--mf-stage-*` with built-in fallbacks.
|
|
227
|
+
- Fit: measure `scrollRef` and feed `computeFitZoomFromExtent({ zoom, scrollWidth, clientWidth })`
|
|
228
|
+
back into `zoom`. It can only zoom out; to fit a rail that already fits, jump
|
|
229
|
+
to 1, re-measure, and correct down.
|
|
230
|
+
|
|
190
231
|
## Tokens
|
|
191
232
|
|
|
192
233
|
```ts
|
package/dist/index.d.mts
CHANGED
|
@@ -649,7 +649,17 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
649
649
|
* optional grant methods, so a pre-CD-5 client keeps working unchanged.
|
|
650
650
|
*/
|
|
651
651
|
type ConnectableTransport = "composio" | "native";
|
|
652
|
+
/**
|
|
653
|
+
* The widest access an entry offers. "write" is retired (DEV-13661: no
|
|
654
|
+
* provider ever only acted, so its old label was never true); it stays in the
|
|
655
|
+
* union so an older server payload still type-checks, and it renders as
|
|
656
|
+
* "Read + write".
|
|
657
|
+
*/
|
|
652
658
|
type ConnectableCapability = "read" | "write" | "readwrite";
|
|
659
|
+
/** What a connection lets Reeve do: ingest/query, or also act (DEV-13661). */
|
|
660
|
+
type ConnectableAccess = "read" | "readwrite";
|
|
661
|
+
/** The ONE access -> words mapping; nothing is labeled as acting alone (DEV-13661). */
|
|
662
|
+
declare function accessLabel(access: ConnectableCapability): string;
|
|
653
663
|
type ConnectionKind = "personal" | "org";
|
|
654
664
|
type ConnectorGranteeType = "user" | "role";
|
|
655
665
|
/** An RBAC role a grant can target, injected via the entry data (CD-2). */
|
|
@@ -806,7 +816,24 @@ interface ConnectableEntry {
|
|
|
806
816
|
* picker never assumes an email shape or synthesizes this itself.
|
|
807
817
|
*/
|
|
808
818
|
account_label?: string | null;
|
|
819
|
+
/**
|
|
820
|
+
* What this live connection lets Reeve do (DEV-13661). Absent on a
|
|
821
|
+
* pre-DEV-13661 payload, where the entry's `capability` stands in.
|
|
822
|
+
*/
|
|
823
|
+
access?: ConnectableAccess | null;
|
|
809
824
|
};
|
|
825
|
+
/**
|
|
826
|
+
* The accesses this entry may be connected as (DEV-13661), in
|
|
827
|
+
* ("read", "readwrite") order. More than one renders a Read / Read + write
|
|
828
|
+
* choice whose pick reaches `client.connect` as `opts.access`.
|
|
829
|
+
*/
|
|
830
|
+
access_options?: ConnectableAccess[] | null;
|
|
831
|
+
/**
|
|
832
|
+
* Every connection provider key that belongs to this entry's provider
|
|
833
|
+
* (its own slug first), so a host can group stored connections onto one
|
|
834
|
+
* row per provider (DEV-13661).
|
|
835
|
+
*/
|
|
836
|
+
provider_keys?: string[] | null;
|
|
810
837
|
/** true = tenant has a live connection but the entry left the allowlist. */
|
|
811
838
|
deprecated: boolean;
|
|
812
839
|
/** Org-connect permission + role options for this entry (CD-4). */
|
|
@@ -841,9 +868,12 @@ interface ConnectorPickerClient {
|
|
|
841
868
|
* composio -> open the returned connect_url; native may resolve with none.
|
|
842
869
|
* `opts.kind` is additive (DEV-5654): a pre-CD-5 client declaring only
|
|
843
870
|
* `connect(entry)` still satisfies this signature and simply ignores it.
|
|
871
|
+
* `opts.access` (DEV-13661) is the row's Read / Read + write pick, sent
|
|
872
|
+
* only when the entry offers a choice.
|
|
844
873
|
*/
|
|
845
874
|
connect(entry: ConnectableEntry, opts?: {
|
|
846
875
|
kind: ConnectionKind;
|
|
876
|
+
access?: ConnectableAccess;
|
|
847
877
|
}): Promise<{
|
|
848
878
|
connect_url?: string;
|
|
849
879
|
}>;
|
|
@@ -895,4 +925,4 @@ interface ConnectorPickerProps {
|
|
|
895
925
|
}
|
|
896
926
|
declare function ConnectorPicker({ client, purpose, lens, layout, onConnected, }: ConnectorPickerProps): react.JSX.Element | null;
|
|
897
927
|
|
|
898
|
-
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
|
928
|
+
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableAccess, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, accessLabel, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
package/dist/index.d.ts
CHANGED
|
@@ -649,7 +649,17 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
649
649
|
* optional grant methods, so a pre-CD-5 client keeps working unchanged.
|
|
650
650
|
*/
|
|
651
651
|
type ConnectableTransport = "composio" | "native";
|
|
652
|
+
/**
|
|
653
|
+
* The widest access an entry offers. "write" is retired (DEV-13661: no
|
|
654
|
+
* provider ever only acted, so its old label was never true); it stays in the
|
|
655
|
+
* union so an older server payload still type-checks, and it renders as
|
|
656
|
+
* "Read + write".
|
|
657
|
+
*/
|
|
652
658
|
type ConnectableCapability = "read" | "write" | "readwrite";
|
|
659
|
+
/** What a connection lets Reeve do: ingest/query, or also act (DEV-13661). */
|
|
660
|
+
type ConnectableAccess = "read" | "readwrite";
|
|
661
|
+
/** The ONE access -> words mapping; nothing is labeled as acting alone (DEV-13661). */
|
|
662
|
+
declare function accessLabel(access: ConnectableCapability): string;
|
|
653
663
|
type ConnectionKind = "personal" | "org";
|
|
654
664
|
type ConnectorGranteeType = "user" | "role";
|
|
655
665
|
/** An RBAC role a grant can target, injected via the entry data (CD-2). */
|
|
@@ -806,7 +816,24 @@ interface ConnectableEntry {
|
|
|
806
816
|
* picker never assumes an email shape or synthesizes this itself.
|
|
807
817
|
*/
|
|
808
818
|
account_label?: string | null;
|
|
819
|
+
/**
|
|
820
|
+
* What this live connection lets Reeve do (DEV-13661). Absent on a
|
|
821
|
+
* pre-DEV-13661 payload, where the entry's `capability` stands in.
|
|
822
|
+
*/
|
|
823
|
+
access?: ConnectableAccess | null;
|
|
809
824
|
};
|
|
825
|
+
/**
|
|
826
|
+
* The accesses this entry may be connected as (DEV-13661), in
|
|
827
|
+
* ("read", "readwrite") order. More than one renders a Read / Read + write
|
|
828
|
+
* choice whose pick reaches `client.connect` as `opts.access`.
|
|
829
|
+
*/
|
|
830
|
+
access_options?: ConnectableAccess[] | null;
|
|
831
|
+
/**
|
|
832
|
+
* Every connection provider key that belongs to this entry's provider
|
|
833
|
+
* (its own slug first), so a host can group stored connections onto one
|
|
834
|
+
* row per provider (DEV-13661).
|
|
835
|
+
*/
|
|
836
|
+
provider_keys?: string[] | null;
|
|
810
837
|
/** true = tenant has a live connection but the entry left the allowlist. */
|
|
811
838
|
deprecated: boolean;
|
|
812
839
|
/** Org-connect permission + role options for this entry (CD-4). */
|
|
@@ -841,9 +868,12 @@ interface ConnectorPickerClient {
|
|
|
841
868
|
* composio -> open the returned connect_url; native may resolve with none.
|
|
842
869
|
* `opts.kind` is additive (DEV-5654): a pre-CD-5 client declaring only
|
|
843
870
|
* `connect(entry)` still satisfies this signature and simply ignores it.
|
|
871
|
+
* `opts.access` (DEV-13661) is the row's Read / Read + write pick, sent
|
|
872
|
+
* only when the entry offers a choice.
|
|
844
873
|
*/
|
|
845
874
|
connect(entry: ConnectableEntry, opts?: {
|
|
846
875
|
kind: ConnectionKind;
|
|
876
|
+
access?: ConnectableAccess;
|
|
847
877
|
}): Promise<{
|
|
848
878
|
connect_url?: string;
|
|
849
879
|
}>;
|
|
@@ -895,4 +925,4 @@ interface ConnectorPickerProps {
|
|
|
895
925
|
}
|
|
896
926
|
declare function ConnectorPicker({ client, purpose, lens, layout, onConnected, }: ConnectorPickerProps): react.JSX.Element | null;
|
|
897
927
|
|
|
898
|
-
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
|
928
|
+
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableAccess, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, accessLabel, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(src_exports, {
|
|
|
45
45
|
REEVE_ACCENT: () => REEVE_ACCENT,
|
|
46
46
|
ResponsiveHeader: () => ResponsiveHeader,
|
|
47
47
|
WORDMARK_WEIGHT: () => WORDMARK_WEIGHT,
|
|
48
|
+
accessLabel: () => accessLabel,
|
|
48
49
|
deriveFallbackLadder: () => deriveFallbackLadder,
|
|
49
50
|
faviconUrl: () => faviconUrl,
|
|
50
51
|
groupByOrg: () => groupByOrg,
|
|
@@ -1463,6 +1464,9 @@ function ContextSwitcher({
|
|
|
1463
1464
|
// src/connector-picker.tsx
|
|
1464
1465
|
var import_react9 = require("react");
|
|
1465
1466
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1467
|
+
function accessLabel(access) {
|
|
1468
|
+
return access === "read" ? "Read" : "Read + write";
|
|
1469
|
+
}
|
|
1466
1470
|
var DEFAULT_CONNECT_ERROR = "Couldn't start the connection. Please try again.";
|
|
1467
1471
|
var MAX_RECONNECT_REFOCUS_CHECKS = 3;
|
|
1468
1472
|
var RECONNECT_UNCONFIRMED_ERROR = "Couldn't confirm the reconnect \u2014 the connection still reports unhealthy. Try again, or disconnect and reconnect.";
|
|
@@ -1484,10 +1488,17 @@ function hasUngroundedPlaceholder(text) {
|
|
|
1484
1488
|
function isDevEnvironment() {
|
|
1485
1489
|
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1486
1490
|
}
|
|
1487
|
-
function
|
|
1488
|
-
if (
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
+
function tileAccess(entry) {
|
|
1492
|
+
if (entry.connection.status === "connected" && entry.connection.access) {
|
|
1493
|
+
return entry.connection.access;
|
|
1494
|
+
}
|
|
1495
|
+
return entry.capability;
|
|
1496
|
+
}
|
|
1497
|
+
function accessChoices(entry) {
|
|
1498
|
+
const options = (entry.access_options ?? []).filter(
|
|
1499
|
+
(a) => a === "read" || a === "readwrite"
|
|
1500
|
+
);
|
|
1501
|
+
return options.length > 1 ? options : [];
|
|
1491
1502
|
}
|
|
1492
1503
|
function errorMessageFrom(err, fallback) {
|
|
1493
1504
|
return err instanceof Error && err.message ? err.message : fallback;
|
|
@@ -1606,7 +1617,7 @@ function ConnectorPicker({
|
|
|
1606
1617
|
};
|
|
1607
1618
|
}, [gated, refreshAfterReturn]);
|
|
1608
1619
|
const handleConnect = (0, import_react9.useCallback)(
|
|
1609
|
-
async (entry, kind) => {
|
|
1620
|
+
async (entry, kind, access) => {
|
|
1610
1621
|
if (isUnhealthy(entry)) {
|
|
1611
1622
|
reconnectingRef.current.add(entry.slug);
|
|
1612
1623
|
} else {
|
|
@@ -1615,7 +1626,10 @@ function ConnectorPicker({
|
|
|
1615
1626
|
reconnectChecksRef.current.delete(entry.slug);
|
|
1616
1627
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "connecting" } }));
|
|
1617
1628
|
try {
|
|
1618
|
-
const result = await clientRef.current.connect(
|
|
1629
|
+
const result = await clientRef.current.connect(
|
|
1630
|
+
entry,
|
|
1631
|
+
access ? { kind, access } : { kind }
|
|
1632
|
+
);
|
|
1619
1633
|
if (result?.connect_url) {
|
|
1620
1634
|
window.open(result.connect_url, "_blank", "noopener,noreferrer");
|
|
1621
1635
|
return;
|
|
@@ -1805,6 +1819,9 @@ function ConnectorTile({
|
|
|
1805
1819
|
const errorMessage = ui?.kind === "error" ? ui.message : null;
|
|
1806
1820
|
const unhealthy = isUnhealthy(entry);
|
|
1807
1821
|
const [kind, setKind] = (0, import_react9.useState)("personal");
|
|
1822
|
+
const choices = accessChoices(entry);
|
|
1823
|
+
const [access, setAccess] = (0, import_react9.useState)(null);
|
|
1824
|
+
const connectAccess = choices.length ? access && choices.includes(access) ? access : choices[choices.length - 1] : void 0;
|
|
1808
1825
|
const [sharingOpen, setSharingOpen] = (0, import_react9.useState)(false);
|
|
1809
1826
|
const [setupOpen, setSetupOpen] = (0, import_react9.useState)(false);
|
|
1810
1827
|
const credentialFields = entry.credential_fields ?? [];
|
|
@@ -1839,7 +1856,7 @@ function ConnectorTile({
|
|
|
1839
1856
|
)
|
|
1840
1857
|
] }),
|
|
1841
1858
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1842
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-testid": `connector-capability-${entry.slug}`, children:
|
|
1859
|
+
(isConnected || choices.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-testid": `connector-capability-${entry.slug}`, children: accessLabel(tileAccess(entry)) }),
|
|
1843
1860
|
isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1844
1861
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
1845
1862
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
@@ -1891,6 +1908,32 @@ function ConnectorTile({
|
|
|
1891
1908
|
children: attribution
|
|
1892
1909
|
}
|
|
1893
1910
|
),
|
|
1911
|
+
!isConnected && choices.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1912
|
+
"div",
|
|
1913
|
+
{
|
|
1914
|
+
"data-testid": `connector-access-choice-${entry.slug}`,
|
|
1915
|
+
role: "group",
|
|
1916
|
+
"aria-label": "Access",
|
|
1917
|
+
className: "mt-1 flex items-center gap-1",
|
|
1918
|
+
children: choices.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1919
|
+
"button",
|
|
1920
|
+
{
|
|
1921
|
+
type: "button",
|
|
1922
|
+
"data-testid": `connector-access-${option}-${entry.slug}`,
|
|
1923
|
+
"aria-pressed": connectAccess === option,
|
|
1924
|
+
disabled: isConnecting,
|
|
1925
|
+
onClick: () => setAccess(option),
|
|
1926
|
+
className: cn(
|
|
1927
|
+
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1928
|
+
connectAccess === option ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1929
|
+
"disabled:opacity-50"
|
|
1930
|
+
),
|
|
1931
|
+
children: accessLabel(option)
|
|
1932
|
+
},
|
|
1933
|
+
option
|
|
1934
|
+
))
|
|
1935
|
+
}
|
|
1936
|
+
),
|
|
1894
1937
|
!isConnected && orgPermitted && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1895
1938
|
"div",
|
|
1896
1939
|
{
|
|
@@ -1944,7 +1987,7 @@ function ConnectorTile({
|
|
|
1944
1987
|
{
|
|
1945
1988
|
type: "button",
|
|
1946
1989
|
"data-testid": `connector-reconnect-${entry.slug}`,
|
|
1947
|
-
onClick: () => onConnect(entry, entry.connection.kind ?? "personal"),
|
|
1990
|
+
onClick: () => onConnect(entry, entry.connection.kind ?? "personal", entry.connection.access ?? void 0),
|
|
1948
1991
|
disabled: isConnecting || isDisconnecting,
|
|
1949
1992
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1950
1993
|
children: isConnecting ? "Reconnecting\u2026" : "Reconnect"
|
|
@@ -1983,7 +2026,7 @@ function ConnectorTile({
|
|
|
1983
2026
|
{
|
|
1984
2027
|
type: "button",
|
|
1985
2028
|
"data-testid": `connector-connect-${entry.slug}`,
|
|
1986
|
-
onClick: () => onConnect(entry, connectKind),
|
|
2029
|
+
onClick: () => onConnect(entry, connectKind, connectAccess),
|
|
1987
2030
|
disabled: isConnecting,
|
|
1988
2031
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1989
2032
|
children: isConnecting ? "Connecting\u2026" : "Connect"
|
|
@@ -2556,6 +2599,7 @@ function ManageSharing({
|
|
|
2556
2599
|
REEVE_ACCENT,
|
|
2557
2600
|
ResponsiveHeader,
|
|
2558
2601
|
WORDMARK_WEIGHT,
|
|
2602
|
+
accessLabel,
|
|
2559
2603
|
deriveFallbackLadder,
|
|
2560
2604
|
faviconUrl,
|
|
2561
2605
|
groupByOrg,
|
package/dist/index.mjs
CHANGED
|
@@ -1407,6 +1407,9 @@ function ContextSwitcher({
|
|
|
1407
1407
|
// src/connector-picker.tsx
|
|
1408
1408
|
import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "react";
|
|
1409
1409
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1410
|
+
function accessLabel(access) {
|
|
1411
|
+
return access === "read" ? "Read" : "Read + write";
|
|
1412
|
+
}
|
|
1410
1413
|
var DEFAULT_CONNECT_ERROR = "Couldn't start the connection. Please try again.";
|
|
1411
1414
|
var MAX_RECONNECT_REFOCUS_CHECKS = 3;
|
|
1412
1415
|
var RECONNECT_UNCONFIRMED_ERROR = "Couldn't confirm the reconnect \u2014 the connection still reports unhealthy. Try again, or disconnect and reconnect.";
|
|
@@ -1428,10 +1431,17 @@ function hasUngroundedPlaceholder(text) {
|
|
|
1428
1431
|
function isDevEnvironment() {
|
|
1429
1432
|
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1430
1433
|
}
|
|
1431
|
-
function
|
|
1432
|
-
if (
|
|
1433
|
-
|
|
1434
|
-
|
|
1434
|
+
function tileAccess(entry) {
|
|
1435
|
+
if (entry.connection.status === "connected" && entry.connection.access) {
|
|
1436
|
+
return entry.connection.access;
|
|
1437
|
+
}
|
|
1438
|
+
return entry.capability;
|
|
1439
|
+
}
|
|
1440
|
+
function accessChoices(entry) {
|
|
1441
|
+
const options = (entry.access_options ?? []).filter(
|
|
1442
|
+
(a) => a === "read" || a === "readwrite"
|
|
1443
|
+
);
|
|
1444
|
+
return options.length > 1 ? options : [];
|
|
1435
1445
|
}
|
|
1436
1446
|
function errorMessageFrom(err, fallback) {
|
|
1437
1447
|
return err instanceof Error && err.message ? err.message : fallback;
|
|
@@ -1550,7 +1560,7 @@ function ConnectorPicker({
|
|
|
1550
1560
|
};
|
|
1551
1561
|
}, [gated, refreshAfterReturn]);
|
|
1552
1562
|
const handleConnect = useCallback4(
|
|
1553
|
-
async (entry, kind) => {
|
|
1563
|
+
async (entry, kind, access) => {
|
|
1554
1564
|
if (isUnhealthy(entry)) {
|
|
1555
1565
|
reconnectingRef.current.add(entry.slug);
|
|
1556
1566
|
} else {
|
|
@@ -1559,7 +1569,10 @@ function ConnectorPicker({
|
|
|
1559
1569
|
reconnectChecksRef.current.delete(entry.slug);
|
|
1560
1570
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "connecting" } }));
|
|
1561
1571
|
try {
|
|
1562
|
-
const result = await clientRef.current.connect(
|
|
1572
|
+
const result = await clientRef.current.connect(
|
|
1573
|
+
entry,
|
|
1574
|
+
access ? { kind, access } : { kind }
|
|
1575
|
+
);
|
|
1563
1576
|
if (result?.connect_url) {
|
|
1564
1577
|
window.open(result.connect_url, "_blank", "noopener,noreferrer");
|
|
1565
1578
|
return;
|
|
@@ -1749,6 +1762,9 @@ function ConnectorTile({
|
|
|
1749
1762
|
const errorMessage = ui?.kind === "error" ? ui.message : null;
|
|
1750
1763
|
const unhealthy = isUnhealthy(entry);
|
|
1751
1764
|
const [kind, setKind] = useState7("personal");
|
|
1765
|
+
const choices = accessChoices(entry);
|
|
1766
|
+
const [access, setAccess] = useState7(null);
|
|
1767
|
+
const connectAccess = choices.length ? access && choices.includes(access) ? access : choices[choices.length - 1] : void 0;
|
|
1752
1768
|
const [sharingOpen, setSharingOpen] = useState7(false);
|
|
1753
1769
|
const [setupOpen, setSetupOpen] = useState7(false);
|
|
1754
1770
|
const credentialFields = entry.credential_fields ?? [];
|
|
@@ -1783,7 +1799,7 @@ function ConnectorTile({
|
|
|
1783
1799
|
)
|
|
1784
1800
|
] }),
|
|
1785
1801
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1786
|
-
/* @__PURE__ */ jsx8("span", { "data-testid": `connector-capability-${entry.slug}`, children:
|
|
1802
|
+
(isConnected || choices.length === 0) && /* @__PURE__ */ jsx8("span", { "data-testid": `connector-capability-${entry.slug}`, children: accessLabel(tileAccess(entry)) }),
|
|
1787
1803
|
isConnected && /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1788
1804
|
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
1789
1805
|
/* @__PURE__ */ jsxs7(
|
|
@@ -1835,6 +1851,32 @@ function ConnectorTile({
|
|
|
1835
1851
|
children: attribution
|
|
1836
1852
|
}
|
|
1837
1853
|
),
|
|
1854
|
+
!isConnected && choices.length > 0 && /* @__PURE__ */ jsx8(
|
|
1855
|
+
"div",
|
|
1856
|
+
{
|
|
1857
|
+
"data-testid": `connector-access-choice-${entry.slug}`,
|
|
1858
|
+
role: "group",
|
|
1859
|
+
"aria-label": "Access",
|
|
1860
|
+
className: "mt-1 flex items-center gap-1",
|
|
1861
|
+
children: choices.map((option) => /* @__PURE__ */ jsx8(
|
|
1862
|
+
"button",
|
|
1863
|
+
{
|
|
1864
|
+
type: "button",
|
|
1865
|
+
"data-testid": `connector-access-${option}-${entry.slug}`,
|
|
1866
|
+
"aria-pressed": connectAccess === option,
|
|
1867
|
+
disabled: isConnecting,
|
|
1868
|
+
onClick: () => setAccess(option),
|
|
1869
|
+
className: cn(
|
|
1870
|
+
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1871
|
+
connectAccess === option ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1872
|
+
"disabled:opacity-50"
|
|
1873
|
+
),
|
|
1874
|
+
children: accessLabel(option)
|
|
1875
|
+
},
|
|
1876
|
+
option
|
|
1877
|
+
))
|
|
1878
|
+
}
|
|
1879
|
+
),
|
|
1838
1880
|
!isConnected && orgPermitted && /* @__PURE__ */ jsxs7(
|
|
1839
1881
|
"div",
|
|
1840
1882
|
{
|
|
@@ -1888,7 +1930,7 @@ function ConnectorTile({
|
|
|
1888
1930
|
{
|
|
1889
1931
|
type: "button",
|
|
1890
1932
|
"data-testid": `connector-reconnect-${entry.slug}`,
|
|
1891
|
-
onClick: () => onConnect(entry, entry.connection.kind ?? "personal"),
|
|
1933
|
+
onClick: () => onConnect(entry, entry.connection.kind ?? "personal", entry.connection.access ?? void 0),
|
|
1892
1934
|
disabled: isConnecting || isDisconnecting,
|
|
1893
1935
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1894
1936
|
children: isConnecting ? "Reconnecting\u2026" : "Reconnect"
|
|
@@ -1927,7 +1969,7 @@ function ConnectorTile({
|
|
|
1927
1969
|
{
|
|
1928
1970
|
type: "button",
|
|
1929
1971
|
"data-testid": `connector-connect-${entry.slug}`,
|
|
1930
|
-
onClick: () => onConnect(entry, connectKind),
|
|
1972
|
+
onClick: () => onConnect(entry, connectKind, connectAccess),
|
|
1931
1973
|
disabled: isConnecting,
|
|
1932
1974
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1933
1975
|
children: isConnecting ? "Connecting\u2026" : "Connect"
|
|
@@ -2499,6 +2541,7 @@ export {
|
|
|
2499
2541
|
REEVE_ACCENT,
|
|
2500
2542
|
ResponsiveHeader,
|
|
2501
2543
|
WORDMARK_WEIGHT,
|
|
2544
|
+
accessLabel,
|
|
2502
2545
|
deriveFallbackLadder,
|
|
2503
2546
|
faviconUrl,
|
|
2504
2547
|
groupByOrg,
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, Ref, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface StageCardContext {
|
|
5
|
+
/** 0-based position in `stages`. */
|
|
6
|
+
index: number;
|
|
7
|
+
selected: boolean;
|
|
8
|
+
/** This card is the one being pointer-dragged. */
|
|
9
|
+
dragging: boolean;
|
|
10
|
+
/** Pointer / Alt+arrow reorder is live — render a drag handle (`StageCardShell dragHandle`). */
|
|
11
|
+
reorderable: boolean;
|
|
12
|
+
/** Calls `onSelect(getId(stage))`. Wire it to `StageCardShell onSelect`. */
|
|
13
|
+
select: () => void;
|
|
14
|
+
}
|
|
15
|
+
interface StageConnectorContext {
|
|
16
|
+
/** `editable` and `onInsertAt` is set. */
|
|
17
|
+
canInsert: boolean;
|
|
18
|
+
/** Calls `onInsertAt(i)`. */
|
|
19
|
+
insert: () => void;
|
|
20
|
+
/** A pointer drag would land a stage in this gap. */
|
|
21
|
+
dropActive: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface StageRailProps<T> {
|
|
24
|
+
stages: T[];
|
|
25
|
+
getId: (stage: T) => string;
|
|
26
|
+
renderCard: (stage: T, index: number, ctx: StageCardContext) => ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* The link between two rendered slots. `prev`/`next` are null for a fixed
|
|
29
|
+
* `leading`/`trailing` slot; `index` is where an inserted stage would land.
|
|
30
|
+
* Return null for no gap. Defaults to an inline `StageConnector`.
|
|
31
|
+
*/
|
|
32
|
+
renderConnector?: (prev: T | null, next: T | null, index: number, ctx: StageConnectorContext) => ReactNode;
|
|
33
|
+
/** Fixed first slot (e.g. a trigger): never reorderable, nothing inserts before it. */
|
|
34
|
+
leading?: ReactNode;
|
|
35
|
+
/** Fixed last slot (e.g. an exit or an append target): nothing inserts after it. */
|
|
36
|
+
trailing?: ReactNode;
|
|
37
|
+
selectedId?: string | null;
|
|
38
|
+
onSelect?: (id: string) => void;
|
|
39
|
+
onInsertAt?: (index: number) => void;
|
|
40
|
+
/** Array-move semantics: `to` is the moved stage's final index. */
|
|
41
|
+
onReorder?: (from: number, to: number) => void;
|
|
42
|
+
/** Opt in to pointer (drag handle) and Alt+←/→ reorder. */
|
|
43
|
+
reorderable?: boolean;
|
|
44
|
+
/** false = read-only: no insert, no reorder. */
|
|
45
|
+
editable?: boolean;
|
|
46
|
+
/** One label per RENDERED slot, fixed slots included, drawn above it. */
|
|
47
|
+
ruler?: {
|
|
48
|
+
label: ReactNode;
|
|
49
|
+
}[];
|
|
50
|
+
/** CSS zoom on the track; pair with `computeFitZoomFromExtent` over `scrollRef`. */
|
|
51
|
+
zoom?: number;
|
|
52
|
+
/** The horizontal scroll element (measure scrollWidth/clientWidth for fit). */
|
|
53
|
+
scrollRef?: Ref<HTMLDivElement>;
|
|
54
|
+
className?: string;
|
|
55
|
+
"aria-label"?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A horizontal "flow of cards": leading slot → stage cards → trailing slot,
|
|
59
|
+
* with connectors between every pair. Domain-free — cards and connectors are
|
|
60
|
+
* the consumer's render props. Snap-scrolls below md.
|
|
61
|
+
*/
|
|
62
|
+
declare function StageRail<T>({ stages, getId, renderCard, renderConnector, leading, trailing, selectedId, onSelect, onInsertAt, onReorder, reorderable, editable, ruler, zoom, scrollRef, className, "aria-label": ariaLabel, }: StageRailProps<T>): react.JSX.Element;
|
|
63
|
+
|
|
64
|
+
/** True when `target` is (inside) an interactive element nested in `root` — not `root` itself. */
|
|
65
|
+
declare function isInteractiveTarget(target: EventTarget | null, root: Element): boolean;
|
|
66
|
+
interface StageCardShellProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
67
|
+
/** Click / Enter / Space on the card itself. Never fires from interactive descendants. */
|
|
68
|
+
onSelect?: () => void;
|
|
69
|
+
selected?: boolean;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
/** Visual only — the body is never replaced. */
|
|
72
|
+
pending?: boolean;
|
|
73
|
+
/** Destructive ring; wins over `selected`. */
|
|
74
|
+
error?: boolean;
|
|
75
|
+
/** Dims the card while a drag (yours or StageRail's) is in flight. */
|
|
76
|
+
dragging?: boolean;
|
|
77
|
+
/** Show the visual drag handle (StageRail's pointer reorder grabs it; HTML5 consumers use `draggable`). */
|
|
78
|
+
dragHandle?: boolean;
|
|
79
|
+
/** Shown verbatim in the bottom-left dot (pass the 1-based number). Omitted when undefined. */
|
|
80
|
+
index?: number;
|
|
81
|
+
topLeft?: ReactNode;
|
|
82
|
+
topRight?: ReactNode;
|
|
83
|
+
/** Centred overlay revealed on card hover (and focus-within unless `overlayRevealOnFocus` is false). */
|
|
84
|
+
overlay?: ReactNode;
|
|
85
|
+
/** Also reveal `overlay` while focus is inside the card. false for bodies that hold focus (e.g. an iframe). */
|
|
86
|
+
overlayRevealOnFocus?: boolean;
|
|
87
|
+
/** Classes for the drag handle, merged last. */
|
|
88
|
+
handleClassName?: string;
|
|
89
|
+
/** Classes for the index dot, merged last. */
|
|
90
|
+
indexClassName?: string;
|
|
91
|
+
/** Bottom strip (e.g. an inline error). */
|
|
92
|
+
alert?: ReactNode;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The frame every stage card shares: ONE root div (ref + rest props land on
|
|
96
|
+
* it, so Radix `asChild` triggers and IntersectionObserver refs work), the
|
|
97
|
+
* consumer's body full-bleed inside, and absolutely-positioned slots over it.
|
|
98
|
+
* Stateless; hover is CSS-only via the `group/card` name.
|
|
99
|
+
*/
|
|
100
|
+
declare const StageCardShell: react.ForwardRefExoticComponent<StageCardShellProps & react.RefAttributes<HTMLDivElement>>;
|
|
101
|
+
|
|
102
|
+
interface StageConnectorProps extends HTMLAttributes<HTMLElement> {
|
|
103
|
+
/** `inline` sits between cards; `append` is the tall end-of-rail target. */
|
|
104
|
+
variant?: "inline" | "append";
|
|
105
|
+
/** Without it (or when `disabled`) the inline `+` is not rendered and the append button is disabled. */
|
|
106
|
+
onInsert?: () => void;
|
|
107
|
+
disabled?: boolean;
|
|
108
|
+
/** Highlight as the live drop target (shows the inline `+` without hover). */
|
|
109
|
+
dropActive?: boolean;
|
|
110
|
+
/** Accessible name of the insert control. */
|
|
111
|
+
insertLabel?: string;
|
|
112
|
+
/** Inline: text / controls under the link (e.g. "2 days", an inline input). */
|
|
113
|
+
label?: ReactNode;
|
|
114
|
+
/** Inline: chip above the link (e.g. "38 waiting"). */
|
|
115
|
+
badge?: ReactNode;
|
|
116
|
+
/** Inline: 0–1 volume, scales the link's thickness (1px → 6px). */
|
|
117
|
+
weight?: number;
|
|
118
|
+
/** Append: the card height to match. Width is max(80, height * 0.45). */
|
|
119
|
+
height?: number;
|
|
120
|
+
/** Append: visible caption. */
|
|
121
|
+
appendText?: ReactNode;
|
|
122
|
+
/** Inline: show the `+` without hover on touch (hover:none) devices. */
|
|
123
|
+
touchAlwaysVisible?: boolean;
|
|
124
|
+
/** Inline: classes for the `+` button, merged last (its drop-active state included). */
|
|
125
|
+
insertClassName?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The link between two stage cards. Rest props (HTML5 onDragOver / onDrop …)
|
|
129
|
+
* land on the hit-area root. Inline with no label/badge/weight it is exactly
|
|
130
|
+
* the 36×36 hit area — zero extra size. Horizontal only.
|
|
131
|
+
*/
|
|
132
|
+
declare function StageConnector({ variant, onInsert, disabled, dropActive, insertLabel, label, badge, weight, height, appendText, touchAlwaysVisible, insertClassName, className, style, onClick, ...rest }: StageConnectorProps): react.JSX.Element;
|
|
133
|
+
|
|
134
|
+
interface StageRailMiniDot {
|
|
135
|
+
/** Names the stage in the accessible summary and the dot's tooltip. */
|
|
136
|
+
label: string;
|
|
137
|
+
key?: string;
|
|
138
|
+
/** Colour per kind, e.g. "bg-primary". */
|
|
139
|
+
className?: string;
|
|
140
|
+
/** Optional tiny icon; the dot grows to fit it. */
|
|
141
|
+
icon?: ReactNode;
|
|
142
|
+
}
|
|
143
|
+
/** Dot-sequence thumbnail of a rail for list rows: one dot per stage. */
|
|
144
|
+
declare function StageRailMini({ dots, className, "aria-label": ariaLabel, }: {
|
|
145
|
+
dots: StageRailMiniDot[];
|
|
146
|
+
className?: string;
|
|
147
|
+
"aria-label"?: string;
|
|
148
|
+
}): react.JSX.Element;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Zoom that fits a rail's content into its scroll viewport, derived from the
|
|
152
|
+
* scroller's REAL rendered extent (ported from the Studio chain, DEV-3681:
|
|
153
|
+
* a closed-form gap model no-opped on overflowing chains).
|
|
154
|
+
*
|
|
155
|
+
* `zoom` is the zoom the extent was rendered AT. Content scales linearly with
|
|
156
|
+
* zoom; the scroller's own horizontal padding (`pad`, StageRail's md+ px-8 =
|
|
157
|
+
* 64) doesn't, so both extents shed it before the ratio. Clamped to
|
|
158
|
+
* [min, max] and rounded to 2dp.
|
|
159
|
+
*
|
|
160
|
+
* Caveat: DOM scrollWidth floor-clamps at clientWidth, so content that already
|
|
161
|
+
* fits measures ratio 1 and this echoes `zoom` — it can only zoom OUT. To fit
|
|
162
|
+
* a fitting rail, jump to `max`, re-measure, and correct down if it overshot.
|
|
163
|
+
*/
|
|
164
|
+
declare function computeFitZoomFromExtent({ zoom, scrollWidth, clientWidth, pad, min, max, }: {
|
|
165
|
+
zoom: number;
|
|
166
|
+
scrollWidth: number;
|
|
167
|
+
clientWidth: number;
|
|
168
|
+
pad?: number;
|
|
169
|
+
min?: number;
|
|
170
|
+
max?: number;
|
|
171
|
+
}): number;
|
|
172
|
+
|
|
173
|
+
export { type StageCardContext, StageCardShell, type StageCardShellProps, StageConnector, type StageConnectorContext, type StageConnectorProps, StageRail, StageRailMini, type StageRailMiniDot, type StageRailProps, computeFitZoomFromExtent, isInteractiveTarget };
|