@burdenoff/fluidgrids-fe-sdk 2026.723.2 → 2026.724.2

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.
@@ -2018,6 +2018,9 @@ var PROVIDER_ICONS = {
2018
2018
  "google-calendar": "logos:google-calendar",
2019
2019
  "google-sheets": "simple-icons:googlesheets",
2020
2020
  "google-docs": "simple-icons:googledocs",
2021
+ "google-chat": "simple-icons:googlechat",
2022
+ "google-forms": "simple-icons:googleforms",
2023
+ "google-workspace-admin-domain-wide-delegation": "logos:google-workspace",
2021
2024
  // Microsoft services
2022
2025
  "microsoft-outlook": "vscode-icons:file-type-outlook",
2023
2026
  "microsoft-onedrive": "simple-icons:onedrive",
@@ -2055,6 +2058,54 @@ var PROVIDER_ICONS = {
2055
2058
  function getProviderIcon(providerKey) {
2056
2059
  return PROVIDER_ICONS[providerKey.toLowerCase()] || PROVIDER_ICONS.generic;
2057
2060
  }
2061
+ function resolveProviderIcon(providerKey, dbIcon) {
2062
+ const key = providerKey.toLowerCase();
2063
+ if (PROVIDER_ICONS[key]) return PROVIDER_ICONS[key];
2064
+ if (dbIcon && dbIcon.includes(":")) return dbIcon;
2065
+ return PROVIDER_ICONS.generic;
2066
+ }
2067
+ function getProviderIconTint(providerKey) {
2068
+ const icon = PROVIDER_ICONS[providerKey.toLowerCase()];
2069
+ if (!icon) return void 0;
2070
+ if (icon.startsWith("simple-icons:") || icon.startsWith("mdi:")) {
2071
+ return PROVIDER_COLORS[providerKey.toLowerCase()];
2072
+ }
2073
+ return void 0;
2074
+ }
2075
+ var PROVIDER_COLORS = {
2076
+ // Google services
2077
+ "google-gmail": "#EA4335",
2078
+ "google-drive": "#4285F4",
2079
+ "google-calendar": "#4285F4",
2080
+ "google-sheets": "#0F9D58",
2081
+ "google-docs": "#4285F4",
2082
+ "google-chat": "#00AC47",
2083
+ "google-forms": "#7248B9",
2084
+ "google-workspace-admin-domain-wide-delegation": "#1A73E8",
2085
+ // Microsoft services
2086
+ "microsoft-outlook": "#0078D4",
2087
+ "microsoft-onedrive": "#0078D4",
2088
+ "microsoft-teams": "#6264A7",
2089
+ "microsoft-excel": "#217346",
2090
+ // Other OAuth2
2091
+ github: "#24292F",
2092
+ slack: "#4A154B",
2093
+ hubspot: "#FF7A59",
2094
+ salesforce: "#00A1E0",
2095
+ notion: "#000000",
2096
+ airtable: "#18BFFF",
2097
+ // API Key
2098
+ openai: "#412991",
2099
+ anthropic: "#D4A373",
2100
+ linear: "#5E6AD2",
2101
+ bigconsole: "#6366F1",
2102
+ sendgrid: "#1A82E2",
2103
+ twilio: "#F22F46",
2104
+ // Generic
2105
+ "generic-oauth2": "#6B7280",
2106
+ "generic-api-key": "#6B7280",
2107
+ "generic-basic-auth": "#6B7280"
2108
+ };
2058
2109
  var AUTH_TYPE_LABELS = {
2059
2110
  OAUTH2: "OAuth2 API",
2060
2111
  OAUTH1: "OAuth1",
@@ -3376,6 +3427,331 @@ function GoogleDocsForm({
3376
3427
  )
3377
3428
  ] });
3378
3429
  }
3430
+ var CHAT_SCOPES = [
3431
+ {
3432
+ scope: "https://www.googleapis.com/auth/chat.messages.readonly",
3433
+ label: "View chat messages"
3434
+ },
3435
+ {
3436
+ scope: "https://www.googleapis.com/auth/chat.messages",
3437
+ label: "View and manage chat messages"
3438
+ },
3439
+ {
3440
+ scope: "https://www.googleapis.com/auth/chat.messages.create",
3441
+ label: "Create chat messages"
3442
+ },
3443
+ {
3444
+ scope: "https://www.googleapis.com/auth/chat.spaces.readonly",
3445
+ label: "View chat spaces"
3446
+ },
3447
+ {
3448
+ scope: "https://www.googleapis.com/auth/chat.spaces",
3449
+ label: "View and manage chat spaces"
3450
+ },
3451
+ {
3452
+ scope: "https://www.googleapis.com/auth/chat.memberships.readonly",
3453
+ label: "View space members"
3454
+ },
3455
+ {
3456
+ scope: "https://www.googleapis.com/auth/chat.memberships",
3457
+ label: "View and manage space members"
3458
+ }
3459
+ ];
3460
+ var DEFAULT_SELECTED = [
3461
+ "https://www.googleapis.com/auth/chat.messages.readonly",
3462
+ "https://www.googleapis.com/auth/chat.spaces.readonly",
3463
+ "https://www.googleapis.com/auth/chat.memberships.readonly"
3464
+ ];
3465
+ function GoogleChatForm({
3466
+ connectionName,
3467
+ connectionDescription,
3468
+ onNameChange,
3469
+ onDescriptionChange,
3470
+ onSubmit,
3471
+ isSubmitting,
3472
+ error
3473
+ }) {
3474
+ const [selectedScopes, setSelectedScopes] = useState(DEFAULT_SELECTED);
3475
+ const toggleScope = useCallback((scope) => {
3476
+ setSelectedScopes(
3477
+ (prev) => prev.includes(scope) ? prev.filter((s) => s !== scope) : [...prev, scope]
3478
+ );
3479
+ }, []);
3480
+ const handleSubmit = useCallback(async () => {
3481
+ await onSubmit({
3482
+ name: connectionName,
3483
+ description: connectionDescription,
3484
+ config: { scopes: selectedScopes }
3485
+ });
3486
+ }, [connectionName, connectionDescription, selectedScopes, onSubmit]);
3487
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
3488
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 rounded-md bg-amber-500/10 border border-amber-500/20", children: [
3489
+ /* @__PURE__ */ jsx(
3490
+ Icon,
3491
+ {
3492
+ icon: "mdi:help-circle",
3493
+ className: "w-4 h-4 text-amber-600 flex-shrink-0"
3494
+ }
3495
+ ),
3496
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-amber-700", children: "Need help filling out these fields?" }),
3497
+ /* @__PURE__ */ jsx(
3498
+ "a",
3499
+ {
3500
+ href: "https://developers.google.com/chat/api/reference/rest",
3501
+ target: "_blank",
3502
+ rel: "noopener noreferrer",
3503
+ className: "text-sm font-medium text-primary hover:underline ml-1",
3504
+ children: "Open docs"
3505
+ }
3506
+ )
3507
+ ] }),
3508
+ /* @__PURE__ */ jsxs("div", { children: [
3509
+ /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: [
3510
+ "Connection Name ",
3511
+ /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
3512
+ ] }),
3513
+ /* @__PURE__ */ jsx(
3514
+ "input",
3515
+ {
3516
+ type: "text",
3517
+ value: connectionName,
3518
+ onChange: (e) => onNameChange(e.target.value),
3519
+ placeholder: "My Google Chat Connection",
3520
+ disabled: isSubmitting,
3521
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
3522
+ }
3523
+ )
3524
+ ] }),
3525
+ /* @__PURE__ */ jsxs("div", { children: [
3526
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: "Description" }),
3527
+ /* @__PURE__ */ jsx(
3528
+ "input",
3529
+ {
3530
+ type: "text",
3531
+ value: connectionDescription,
3532
+ onChange: (e) => onDescriptionChange(e.target.value),
3533
+ placeholder: "Optional description",
3534
+ disabled: isSubmitting,
3535
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
3536
+ }
3537
+ )
3538
+ ] }),
3539
+ /* @__PURE__ */ jsxs("div", { children: [
3540
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-2", children: "Chat Permissions" }),
3541
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5 max-h-48 overflow-y-auto border border-border rounded-md p-3", children: CHAT_SCOPES.map(({ scope, label }) => /* @__PURE__ */ jsxs(
3542
+ "label",
3543
+ {
3544
+ className: "flex items-center gap-2 cursor-pointer hover:bg-accent/50 px-2 py-1 rounded",
3545
+ children: [
3546
+ /* @__PURE__ */ jsx(
3547
+ "input",
3548
+ {
3549
+ type: "checkbox",
3550
+ checked: selectedScopes.includes(scope),
3551
+ onChange: () => toggleScope(scope),
3552
+ disabled: isSubmitting,
3553
+ className: "rounded border-border"
3554
+ }
3555
+ ),
3556
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: label })
3557
+ ]
3558
+ },
3559
+ scope
3560
+ )) }),
3561
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Basic scopes (openid, email, profile) are always included" })
3562
+ ] }),
3563
+ /* @__PURE__ */ jsx("div", { className: "p-3 rounded-md bg-blue-500/10 border border-blue-500/20", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
3564
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:open-in-new", className: "w-4 h-4" }),
3565
+ "A popup window will open for Google sign-in"
3566
+ ] }) }),
3567
+ error && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-md bg-destructive/10 border border-destructive/20", children: [
3568
+ /* @__PURE__ */ jsx(
3569
+ Icon,
3570
+ {
3571
+ icon: "mdi:alert-circle",
3572
+ className: "w-4 h-4 text-destructive flex-shrink-0"
3573
+ }
3574
+ ),
3575
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: error })
3576
+ ] }),
3577
+ /* @__PURE__ */ jsxs(
3578
+ "button",
3579
+ {
3580
+ type: "button",
3581
+ onClick: handleSubmit,
3582
+ disabled: isSubmitting || !connectionName.trim(),
3583
+ className: "inline-flex items-center gap-2.5 px-4 py-2.5 text-sm font-medium rounded-md bg-white border border-border text-foreground hover:bg-accent transition-colors disabled:opacity-50 shadow-sm",
3584
+ children: [
3585
+ isSubmitting ? /* @__PURE__ */ jsx(Icon, { icon: "mdi:loading", className: "w-5 h-5 animate-spin" }) : /* @__PURE__ */ jsx(
3586
+ Icon,
3587
+ {
3588
+ icon: "simple-icons:googlechat",
3589
+ className: "w-5 h-5",
3590
+ style: { color: "#00AC47" }
3591
+ }
3592
+ ),
3593
+ isSubmitting ? "Waiting for authorization..." : "Sign in with Google"
3594
+ ]
3595
+ }
3596
+ )
3597
+ ] });
3598
+ }
3599
+ var FORMS_SCOPES = [
3600
+ {
3601
+ scope: "https://www.googleapis.com/auth/forms.body.readonly",
3602
+ label: "View form structure"
3603
+ },
3604
+ {
3605
+ scope: "https://www.googleapis.com/auth/forms.body",
3606
+ label: "Create and edit forms"
3607
+ },
3608
+ {
3609
+ scope: "https://www.googleapis.com/auth/forms.responses.readonly",
3610
+ label: "View form responses"
3611
+ },
3612
+ {
3613
+ scope: "https://www.googleapis.com/auth/drive.readonly",
3614
+ label: "View Drive files (for form discovery)"
3615
+ }
3616
+ ];
3617
+ var DEFAULT_SELECTED2 = [
3618
+ "https://www.googleapis.com/auth/forms.body.readonly",
3619
+ "https://www.googleapis.com/auth/forms.responses.readonly"
3620
+ ];
3621
+ function GoogleFormsForm({
3622
+ connectionName,
3623
+ connectionDescription,
3624
+ onNameChange,
3625
+ onDescriptionChange,
3626
+ onSubmit,
3627
+ isSubmitting,
3628
+ error
3629
+ }) {
3630
+ const [selectedScopes, setSelectedScopes] = useState(DEFAULT_SELECTED2);
3631
+ const toggleScope = useCallback((scope) => {
3632
+ setSelectedScopes(
3633
+ (prev) => prev.includes(scope) ? prev.filter((s) => s !== scope) : [...prev, scope]
3634
+ );
3635
+ }, []);
3636
+ const handleSubmit = useCallback(async () => {
3637
+ await onSubmit({
3638
+ name: connectionName,
3639
+ description: connectionDescription,
3640
+ config: { scopes: selectedScopes }
3641
+ });
3642
+ }, [connectionName, connectionDescription, selectedScopes, onSubmit]);
3643
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
3644
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 rounded-md bg-amber-500/10 border border-amber-500/20", children: [
3645
+ /* @__PURE__ */ jsx(
3646
+ Icon,
3647
+ {
3648
+ icon: "mdi:help-circle",
3649
+ className: "w-4 h-4 text-amber-600 flex-shrink-0"
3650
+ }
3651
+ ),
3652
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-amber-700", children: "Need help filling out these fields?" }),
3653
+ /* @__PURE__ */ jsx(
3654
+ "a",
3655
+ {
3656
+ href: "https://developers.google.com/forms/api/reference/rest",
3657
+ target: "_blank",
3658
+ rel: "noopener noreferrer",
3659
+ className: "text-sm font-medium text-primary hover:underline ml-1",
3660
+ children: "Open docs"
3661
+ }
3662
+ )
3663
+ ] }),
3664
+ /* @__PURE__ */ jsxs("div", { children: [
3665
+ /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: [
3666
+ "Connection Name ",
3667
+ /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
3668
+ ] }),
3669
+ /* @__PURE__ */ jsx(
3670
+ "input",
3671
+ {
3672
+ type: "text",
3673
+ value: connectionName,
3674
+ onChange: (e) => onNameChange(e.target.value),
3675
+ placeholder: "My Google Forms Connection",
3676
+ disabled: isSubmitting,
3677
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
3678
+ }
3679
+ )
3680
+ ] }),
3681
+ /* @__PURE__ */ jsxs("div", { children: [
3682
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: "Description" }),
3683
+ /* @__PURE__ */ jsx(
3684
+ "input",
3685
+ {
3686
+ type: "text",
3687
+ value: connectionDescription,
3688
+ onChange: (e) => onDescriptionChange(e.target.value),
3689
+ placeholder: "Optional description",
3690
+ disabled: isSubmitting,
3691
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
3692
+ }
3693
+ )
3694
+ ] }),
3695
+ /* @__PURE__ */ jsxs("div", { children: [
3696
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-2", children: "Forms Permissions" }),
3697
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5 max-h-48 overflow-y-auto border border-border rounded-md p-3", children: FORMS_SCOPES.map(({ scope, label }) => /* @__PURE__ */ jsxs(
3698
+ "label",
3699
+ {
3700
+ className: "flex items-center gap-2 cursor-pointer hover:bg-accent/50 px-2 py-1 rounded",
3701
+ children: [
3702
+ /* @__PURE__ */ jsx(
3703
+ "input",
3704
+ {
3705
+ type: "checkbox",
3706
+ checked: selectedScopes.includes(scope),
3707
+ onChange: () => toggleScope(scope),
3708
+ disabled: isSubmitting,
3709
+ className: "rounded border-border"
3710
+ }
3711
+ ),
3712
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: label })
3713
+ ]
3714
+ },
3715
+ scope
3716
+ )) }),
3717
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Basic scopes (openid, email, profile) are always included" })
3718
+ ] }),
3719
+ /* @__PURE__ */ jsx("div", { className: "p-3 rounded-md bg-blue-500/10 border border-blue-500/20", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
3720
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:open-in-new", className: "w-4 h-4" }),
3721
+ "A popup window will open for Google sign-in"
3722
+ ] }) }),
3723
+ error && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-md bg-destructive/10 border border-destructive/20", children: [
3724
+ /* @__PURE__ */ jsx(
3725
+ Icon,
3726
+ {
3727
+ icon: "mdi:alert-circle",
3728
+ className: "w-4 h-4 text-destructive flex-shrink-0"
3729
+ }
3730
+ ),
3731
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: error })
3732
+ ] }),
3733
+ /* @__PURE__ */ jsxs(
3734
+ "button",
3735
+ {
3736
+ type: "button",
3737
+ onClick: handleSubmit,
3738
+ disabled: isSubmitting || !connectionName.trim(),
3739
+ className: "inline-flex items-center gap-2.5 px-4 py-2.5 text-sm font-medium rounded-md bg-white border border-border text-foreground hover:bg-accent transition-colors disabled:opacity-50 shadow-sm",
3740
+ children: [
3741
+ isSubmitting ? /* @__PURE__ */ jsx(Icon, { icon: "mdi:loading", className: "w-5 h-5 animate-spin" }) : /* @__PURE__ */ jsx(
3742
+ Icon,
3743
+ {
3744
+ icon: "simple-icons:googleforms",
3745
+ className: "w-5 h-5",
3746
+ style: { color: "#7248B9" }
3747
+ }
3748
+ ),
3749
+ isSubmitting ? "Waiting for authorization..." : "Sign in with Google"
3750
+ ]
3751
+ }
3752
+ )
3753
+ ] });
3754
+ }
3379
3755
  var OUTLOOK_SCOPES = [
3380
3756
  { scope: "Mail.Read", label: "Read your mail" },
3381
3757
  { scope: "Mail.ReadWrite", label: "Read and write your mail" },
@@ -6335,6 +6711,191 @@ function GenericBasicAuthForm({
6335
6711
  )
6336
6712
  ] });
6337
6713
  }
6714
+ function asConfigSchema(raw) {
6715
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
6716
+ return null;
6717
+ }
6718
+ const candidate = raw;
6719
+ if (typeof candidate.properties !== "object" || candidate.properties === null) {
6720
+ return null;
6721
+ }
6722
+ return {
6723
+ type: "object",
6724
+ properties: candidate.properties,
6725
+ required: Array.isArray(candidate.required) ? candidate.required : []
6726
+ };
6727
+ }
6728
+ function CustomConfigForm({
6729
+ provider,
6730
+ connectionName,
6731
+ connectionDescription,
6732
+ onNameChange,
6733
+ onDescriptionChange,
6734
+ onSubmit,
6735
+ isSubmitting,
6736
+ error
6737
+ }) {
6738
+ const schema = useMemo(
6739
+ () => asConfigSchema(provider.configSchema),
6740
+ [provider.configSchema]
6741
+ );
6742
+ const [values, setValues] = useState({});
6743
+ const [validationError, setValidationError] = useState();
6744
+ const setValue = useCallback((field, value) => {
6745
+ setValues((prev) => ({ ...prev, [field]: value }));
6746
+ setValidationError(void 0);
6747
+ }, []);
6748
+ const requiredFields = useMemo(
6749
+ () => new Set(schema?.required ?? []),
6750
+ [schema]
6751
+ );
6752
+ const handleSubmit = useCallback(async () => {
6753
+ if (!schema) return;
6754
+ for (const field of schema.required ?? []) {
6755
+ if (!values[field]?.trim()) {
6756
+ setValidationError(
6757
+ `${schema.properties[field]?.title ?? field} is required`
6758
+ );
6759
+ return;
6760
+ }
6761
+ }
6762
+ const config2 = {};
6763
+ for (const field of Object.keys(schema.properties)) {
6764
+ const value = values[field]?.trim();
6765
+ if (value) config2[field] = value;
6766
+ }
6767
+ await onSubmit({
6768
+ name: connectionName,
6769
+ description: connectionDescription,
6770
+ config: config2
6771
+ });
6772
+ }, [schema, values, connectionName, connectionDescription, onSubmit]);
6773
+ if (!schema) {
6774
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-md bg-destructive/10 border border-destructive/20", children: [
6775
+ /* @__PURE__ */ jsx(
6776
+ Icon,
6777
+ {
6778
+ icon: "mdi:alert-circle",
6779
+ className: "w-4 h-4 text-destructive flex-shrink-0"
6780
+ }
6781
+ ),
6782
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: "This provider does not declare a configuration form." })
6783
+ ] });
6784
+ }
6785
+ const displayError = validationError ?? error;
6786
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
6787
+ provider.docsUrl && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5 rounded-md bg-amber-500/10 border border-amber-500/20", children: [
6788
+ /* @__PURE__ */ jsx(
6789
+ Icon,
6790
+ {
6791
+ icon: "mdi:help-circle",
6792
+ className: "w-4 h-4 text-amber-600 flex-shrink-0"
6793
+ }
6794
+ ),
6795
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-amber-700", children: "Need help filling out these fields?" }),
6796
+ /* @__PURE__ */ jsx(
6797
+ "a",
6798
+ {
6799
+ href: provider.docsUrl,
6800
+ target: "_blank",
6801
+ rel: "noopener noreferrer",
6802
+ className: "text-sm font-medium text-primary hover:underline ml-1",
6803
+ children: "Open docs"
6804
+ }
6805
+ )
6806
+ ] }),
6807
+ /* @__PURE__ */ jsxs("div", { children: [
6808
+ /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: [
6809
+ "Connection Name ",
6810
+ /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
6811
+ ] }),
6812
+ /* @__PURE__ */ jsx(
6813
+ "input",
6814
+ {
6815
+ type: "text",
6816
+ value: connectionName,
6817
+ onChange: (e) => onNameChange(e.target.value),
6818
+ placeholder: `My ${provider.name} Connection`,
6819
+ disabled: isSubmitting,
6820
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
6821
+ }
6822
+ )
6823
+ ] }),
6824
+ /* @__PURE__ */ jsxs("div", { children: [
6825
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: "Description" }),
6826
+ /* @__PURE__ */ jsx(
6827
+ "input",
6828
+ {
6829
+ type: "text",
6830
+ value: connectionDescription,
6831
+ onChange: (e) => onDescriptionChange(e.target.value),
6832
+ placeholder: "Optional description",
6833
+ disabled: isSubmitting,
6834
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
6835
+ }
6836
+ )
6837
+ ] }),
6838
+ Object.entries(schema.properties).map(([field, def]) => /* @__PURE__ */ jsxs("div", { children: [
6839
+ /* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: [
6840
+ def.title ?? field,
6841
+ " ",
6842
+ requiredFields.has(field) && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
6843
+ ] }),
6844
+ def.secret ? /* @__PURE__ */ jsx(
6845
+ "textarea",
6846
+ {
6847
+ value: values[field] ?? "",
6848
+ onChange: (e) => setValue(field, e.target.value),
6849
+ placeholder: def.description,
6850
+ disabled: isSubmitting,
6851
+ rows: 4,
6852
+ autoComplete: "off",
6853
+ spellCheck: false,
6854
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm font-mono focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
6855
+ }
6856
+ ) : /* @__PURE__ */ jsx(
6857
+ "input",
6858
+ {
6859
+ type: "text",
6860
+ value: values[field] ?? "",
6861
+ onChange: (e) => setValue(field, e.target.value),
6862
+ placeholder: def.description,
6863
+ disabled: isSubmitting,
6864
+ autoComplete: "off",
6865
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background text-sm focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary disabled:opacity-50"
6866
+ }
6867
+ ),
6868
+ def.description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: def.description })
6869
+ ] }, field)),
6870
+ /* @__PURE__ */ jsx("div", { className: "p-3 rounded-md bg-blue-500/10 border border-blue-500/20", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
6871
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:shield-lock", className: "w-4 h-4" }),
6872
+ "Secret fields are stored encrypted and never shown again."
6873
+ ] }) }),
6874
+ displayError && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-md bg-destructive/10 border border-destructive/20", children: [
6875
+ /* @__PURE__ */ jsx(
6876
+ Icon,
6877
+ {
6878
+ icon: "mdi:alert-circle",
6879
+ className: "w-4 h-4 text-destructive flex-shrink-0"
6880
+ }
6881
+ ),
6882
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: displayError })
6883
+ ] }),
6884
+ /* @__PURE__ */ jsxs(
6885
+ "button",
6886
+ {
6887
+ type: "button",
6888
+ onClick: handleSubmit,
6889
+ disabled: isSubmitting || !connectionName.trim(),
6890
+ className: "inline-flex items-center gap-2.5 px-4 py-2.5 text-sm font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50",
6891
+ children: [
6892
+ isSubmitting ? /* @__PURE__ */ jsx(Icon, { icon: "mdi:loading", className: "w-5 h-5 animate-spin" }) : /* @__PURE__ */ jsx(Icon, { icon: "mdi:content-save", className: "w-5 h-5" }),
6893
+ isSubmitting ? "Saving..." : "Save connection"
6894
+ ]
6895
+ }
6896
+ )
6897
+ ] });
6898
+ }
6338
6899
 
6339
6900
  // src/modules/connections/components/provider-forms/index.ts
6340
6901
  var PROVIDER_FORM_REGISTRY = {
@@ -6344,6 +6905,9 @@ var PROVIDER_FORM_REGISTRY = {
6344
6905
  "google-calendar": GoogleCalendarForm,
6345
6906
  "google-sheets": GoogleSheetsForm,
6346
6907
  "google-docs": GoogleDocsForm,
6908
+ "google-chat": GoogleChatForm,
6909
+ "google-forms": GoogleFormsForm,
6910
+ "google-workspace-admin-domain-wide-delegation": CustomConfigForm,
6347
6911
  // Microsoft services
6348
6912
  "microsoft-outlook": MicrosoftOutlookForm,
6349
6913
  "microsoft-onedrive": MicrosoftOneDriveForm,
@@ -6378,6 +6942,8 @@ function getBaseFormByAuthType(authType) {
6378
6942
  return BasicAuthBaseForm;
6379
6943
  case "BEARER_TOKEN":
6380
6944
  return BearerTokenBaseForm;
6945
+ case "CUSTOM":
6946
+ return CustomConfigForm;
6381
6947
  default:
6382
6948
  return ApiKeyBaseForm;
6383
6949
  }
@@ -6464,7 +7030,8 @@ function ProviderPicker({
6464
7030
  Icon,
6465
7031
  {
6466
7032
  icon: getProviderIcon(provider.key),
6467
- className: "w-6 h-6 flex-shrink-0"
7033
+ className: "w-6 h-6 flex-shrink-0",
7034
+ style: { color: getProviderIconTint(provider.key) }
6468
7035
  }
6469
7036
  ),
6470
7037
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
@@ -6610,6 +7177,21 @@ var AUTHENTICATE_WITH_BEARER_TOKEN = gql`
6610
7177
  }
6611
7178
  }
6612
7179
  `;
7180
+ var AUTHENTICATE_WITH_CUSTOM_CONFIG = gql`
7181
+ mutation AuthenticateWithCustomConfig($input: CustomConfigAuthInput!) {
7182
+ authenticateWithCustomConfig(input: $input) {
7183
+ id
7184
+ name
7185
+ status
7186
+ provider {
7187
+ id
7188
+ key
7189
+ name
7190
+ icon
7191
+ }
7192
+ }
7193
+ }
7194
+ `;
6613
7195
  var TEST_CONNECTION = gql`
6614
7196
  mutation TestConnection($connectionId: ID!) {
6615
7197
  testConnection(connectionId: $connectionId) {
@@ -6706,7 +7288,11 @@ function useConnectionDialog(options) {
6706
7288
  name: data.name.trim(),
6707
7289
  description: data.description?.trim(),
6708
7290
  providerId: data.provider.id,
6709
- config: data.config
7291
+ // CUSTOM providers: config carries secrets (e.g. service-account
7292
+ // JSON), so it must NOT land in the plain connection.config
7293
+ // column — it is only sent to authenticateWithCustomConfig,
7294
+ // which stores it in the encrypted credential payload.
7295
+ config: data.provider.authType === "CUSTOM" ? void 0 : data.config
6710
7296
  }
6711
7297
  }
6712
7298
  })
@@ -6873,6 +7459,32 @@ function useConnectionDialog(options) {
6873
7459
  }
6874
7460
  break;
6875
7461
  }
7462
+ case "CUSTOM": {
7463
+ if (!data.config || Object.keys(data.config).length === 0) {
7464
+ throw new Error("Connection config is required");
7465
+ }
7466
+ const customResult = throwIfResultError(
7467
+ await client.mutate({
7468
+ mutation: AUTHENTICATE_WITH_CUSTOM_CONFIG,
7469
+ variables: {
7470
+ input: {
7471
+ connectionId: connection.id,
7472
+ config: data.config
7473
+ }
7474
+ }
7475
+ })
7476
+ );
7477
+ const conn = customResult.data?.authenticateWithCustomConfig;
7478
+ if (conn) {
7479
+ options?.onConnectionCreated?.({
7480
+ id: conn.id,
7481
+ name: conn.name,
7482
+ provider: conn.provider,
7483
+ status: conn.status
7484
+ });
7485
+ }
7486
+ break;
7487
+ }
6876
7488
  default:
6877
7489
  options?.onConnectionCreated?.({
6878
7490
  id: connection.id,
@@ -7021,8 +7633,14 @@ function ConnectionFormDialog({
7021
7633
  /* @__PURE__ */ jsx(
7022
7634
  Icon,
7023
7635
  {
7024
- icon: getProviderIcon(selectedProvider.key),
7025
- className: "w-7 h-7"
7636
+ icon: resolveProviderIcon(
7637
+ selectedProvider.key,
7638
+ selectedProvider.icon
7639
+ ),
7640
+ className: "w-7 h-7",
7641
+ style: {
7642
+ color: getProviderIconTint(selectedProvider.key)
7643
+ }
7026
7644
  }
7027
7645
  ),
7028
7646
  /* @__PURE__ */ jsxs("div", { children: [
@@ -7150,8 +7768,14 @@ function ConnectionFormDialog({
7150
7768
  /* @__PURE__ */ jsx(
7151
7769
  Icon,
7152
7770
  {
7153
- icon: getProviderIcon(selectedProvider.key),
7154
- className: "w-8 h-8"
7771
+ icon: resolveProviderIcon(
7772
+ selectedProvider.key,
7773
+ selectedProvider.icon
7774
+ ),
7775
+ className: "w-8 h-8",
7776
+ style: {
7777
+ color: getProviderIconTint(selectedProvider.key)
7778
+ }
7155
7779
  }
7156
7780
  ),
7157
7781
  /* @__PURE__ */ jsxs("div", { children: [
@@ -7245,11 +7869,18 @@ function ConnectionChip({
7245
7869
  onRemove
7246
7870
  }) {
7247
7871
  const providerKey = connectionData?.provider?.key || connection.adapter;
7248
- const icon = connectionData?.provider?.icon || getProviderIcon(providerKey);
7872
+ const icon = resolveProviderIcon(providerKey, connectionData?.provider?.icon);
7249
7873
  const name = connectionData?.name || connection.connectionId;
7250
7874
  const status = connectionData?.status;
7251
7875
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-2 py-1 bg-muted rounded-md text-sm group", children: [
7252
- /* @__PURE__ */ jsx(Icon, { icon, className: "w-4 h-4" }),
7876
+ /* @__PURE__ */ jsx(
7877
+ Icon,
7878
+ {
7879
+ icon,
7880
+ className: "w-4 h-4",
7881
+ style: { color: getProviderIconTint(providerKey) }
7882
+ }
7883
+ ),
7253
7884
  /* @__PURE__ */ jsx("span", { className: "truncate max-w-32", children: name }),
7254
7885
  status && /* @__PURE__ */ jsx(
7255
7886
  Icon,
@@ -7481,8 +8112,16 @@ function ConnectionSelector({
7481
8112
  /* @__PURE__ */ jsx(
7482
8113
  Icon,
7483
8114
  {
7484
- icon: conns[0]?.provider?.icon || getProviderIcon(conns[0]?.provider?.key || ""),
7485
- className: "w-4 h-4"
8115
+ icon: resolveProviderIcon(
8116
+ conns[0]?.provider?.key || "",
8117
+ conns[0]?.provider?.icon
8118
+ ),
8119
+ className: "w-4 h-4",
8120
+ style: {
8121
+ color: getProviderIconTint(
8122
+ conns[0]?.provider?.key || ""
8123
+ )
8124
+ }
7486
8125
  }
7487
8126
  ),
7488
8127
  providerName
@@ -9251,7 +9890,7 @@ function SubNodeComponent({
9251
9890
  children: /* @__PURE__ */ jsx(Icon, { icon: meta.icon, className: "w-7 h-7 text-accent opacity-80" })
9252
9891
  }
9253
9892
  ),
9254
- /* @__PURE__ */ jsx("span", { className: "mt-1.5 text-xs text-[var(--color-text-secondary)] font-medium text-center max-w-24 leading-tight", children: meta.title }),
9893
+ /* @__PURE__ */ jsx("span", { className: "mt-1.5 text-xs text-[var(--color-text-secondary)] font-medium text-center max-w-24 leading-tight", children: data?.label || data?.args?.state?.operation || meta.title }),
9255
9894
  /* @__PURE__ */ jsx(
9256
9895
  "button",
9257
9896
  {
@@ -9798,5 +10437,5 @@ function registerWorkflowNodeTypes(workflowNodes) {
9798
10437
  }
9799
10438
 
9800
10439
  export { AVAILABLE_NODES, ConfigSchemaForm, ConnectionFormDialog, ConnectionSelector, NODES, NODES_METADATA, NODE_CONFIGS, NODE_TYPES, NodePropertyPanel, ProviderPicker, ensureNodeConfigsLoaded, fetchNodeManifest, getNodeDetail, getNodeMetadata, getProviderForm, isNodeConfigsInitialized, listCustomBlocks, onNodeTypesUpdate, refetchStoreNodes, registerCustomBlock, registerWorkflowNodeTypes, resolveUiSpec, stripSubmitActions, useConnection, useConnectionDialog, useConnections, useConnectionsByProvider, useCreateConnection, useInitiateOAuth, useInsertNode, useNodeExecution, useProviderByKey, useProviderCatalog, useProviders, useSaveWorkflow };
9801
- //# sourceMappingURL=chunk-VICF7CEB.js.map
9802
- //# sourceMappingURL=chunk-VICF7CEB.js.map
10440
+ //# sourceMappingURL=chunk-EVKWBOYH.js.map
10441
+ //# sourceMappingURL=chunk-EVKWBOYH.js.map