@datatechsolutions/ui 3.9.1 → 3.10.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.
Files changed (95) hide show
  1. package/dist/astrlabe/index.js +107 -107
  2. package/dist/astrlabe/index.mjs +3 -3
  3. package/dist/astrlabe/workflow-canvas.js +3 -3
  4. package/dist/astrlabe/workflow-canvas.mjs +2 -2
  5. package/dist/{chunk-ZDXEGSCF.js → chunk-2A45ZEK4.js} +45 -45
  6. package/dist/{chunk-ZDXEGSCF.js.map → chunk-2A45ZEK4.js.map} +1 -1
  7. package/dist/{chunk-T4IYOKHR.js → chunk-5AKTDJFR.js} +25 -25
  8. package/dist/{chunk-T4IYOKHR.js.map → chunk-5AKTDJFR.js.map} +1 -1
  9. package/dist/{chunk-ZQRUAXGP.mjs → chunk-5KI7FB3E.mjs} +188 -48
  10. package/dist/chunk-5KI7FB3E.mjs.map +1 -0
  11. package/dist/{chunk-GQWC4EKE.mjs → chunk-5U43K6G3.mjs} +4 -4
  12. package/dist/{chunk-GQWC4EKE.mjs.map → chunk-5U43K6G3.mjs.map} +1 -1
  13. package/dist/{chunk-PD3JLDA5.mjs → chunk-6UX2SRA2.mjs} +3 -3
  14. package/dist/{chunk-PD3JLDA5.mjs.map → chunk-6UX2SRA2.mjs.map} +1 -1
  15. package/dist/{chunk-2ZY3IQ2I.mjs → chunk-6ZYATZS3.mjs} +3 -3
  16. package/dist/{chunk-2ZY3IQ2I.mjs.map → chunk-6ZYATZS3.mjs.map} +1 -1
  17. package/dist/{chunk-AXBD6OAF.mjs → chunk-A256OE5E.mjs} +11 -11
  18. package/dist/{chunk-AXBD6OAF.mjs.map → chunk-A256OE5E.mjs.map} +1 -1
  19. package/dist/{chunk-DQIEVLA3.js → chunk-AMESLEIO.js} +35 -35
  20. package/dist/{chunk-DQIEVLA3.js.map → chunk-AMESLEIO.js.map} +1 -1
  21. package/dist/{chunk-6E2YH67A.js → chunk-B76RTA7D.js} +35 -35
  22. package/dist/{chunk-6E2YH67A.js.map → chunk-B76RTA7D.js.map} +1 -1
  23. package/dist/{chunk-OVQ4MKCV.mjs → chunk-BU4WMSK3.mjs} +3 -3
  24. package/dist/{chunk-OVQ4MKCV.mjs.map → chunk-BU4WMSK3.mjs.map} +1 -1
  25. package/dist/{chunk-WS3IJFPW.mjs → chunk-C4D3EI5L.mjs} +3 -3
  26. package/dist/{chunk-WS3IJFPW.mjs.map → chunk-C4D3EI5L.mjs.map} +1 -1
  27. package/dist/{chunk-EAIE4QGD.mjs → chunk-DA3H7ERQ.mjs} +20 -20
  28. package/dist/{chunk-EAIE4QGD.mjs.map → chunk-DA3H7ERQ.mjs.map} +1 -1
  29. package/dist/{chunk-U6VFS3RD.js → chunk-EC34PGUO.js} +142 -142
  30. package/dist/{chunk-U6VFS3RD.js.map → chunk-EC34PGUO.js.map} +1 -1
  31. package/dist/{chunk-6QJI5YOJ.mjs → chunk-FD376DZ6.mjs} +3 -3
  32. package/dist/{chunk-6QJI5YOJ.mjs.map → chunk-FD376DZ6.mjs.map} +1 -1
  33. package/dist/{chunk-ZQEMKEEH.mjs → chunk-FENA4YGN.mjs} +3 -3
  34. package/dist/{chunk-ZQEMKEEH.mjs.map → chunk-FENA4YGN.mjs.map} +1 -1
  35. package/dist/{chunk-R6GEJBFC.js → chunk-FIJMOTP4.js} +34 -34
  36. package/dist/{chunk-R6GEJBFC.js.map → chunk-FIJMOTP4.js.map} +1 -1
  37. package/dist/{chunk-BWUFLW5W.mjs → chunk-H7X3SXMB.mjs} +6 -6
  38. package/dist/{chunk-BWUFLW5W.mjs.map → chunk-H7X3SXMB.mjs.map} +1 -1
  39. package/dist/{chunk-OEZ7GAJY.mjs → chunk-HEXTU6W3.mjs} +6 -6
  40. package/dist/{chunk-OEZ7GAJY.mjs.map → chunk-HEXTU6W3.mjs.map} +1 -1
  41. package/dist/{chunk-2E7HYTS7.mjs → chunk-JB3U6ORY.mjs} +3 -3
  42. package/dist/{chunk-2E7HYTS7.mjs.map → chunk-JB3U6ORY.mjs.map} +1 -1
  43. package/dist/{chunk-A2RIX2RK.js → chunk-KHUWFL6W.js} +4 -4
  44. package/dist/{chunk-A2RIX2RK.js.map → chunk-KHUWFL6W.js.map} +1 -1
  45. package/dist/{chunk-CRBGZA6Y.js → chunk-L3R425GB.js} +13 -13
  46. package/dist/{chunk-CRBGZA6Y.js.map → chunk-L3R425GB.js.map} +1 -1
  47. package/dist/{chunk-MT66VKLS.js → chunk-LVR4SR65.js} +189 -47
  48. package/dist/chunk-LVR4SR65.js.map +1 -0
  49. package/dist/{chunk-UZIICTIY.js → chunk-MAOZWOA6.js} +55 -55
  50. package/dist/{chunk-UZIICTIY.js.map → chunk-MAOZWOA6.js.map} +1 -1
  51. package/dist/{chunk-WJENX6KB.js → chunk-MSMEECO6.js} +9 -9
  52. package/dist/{chunk-WJENX6KB.js.map → chunk-MSMEECO6.js.map} +1 -1
  53. package/dist/{chunk-SJ6SUS7H.mjs → chunk-NM37GLCL.mjs} +3 -3
  54. package/dist/{chunk-SJ6SUS7H.mjs.map → chunk-NM37GLCL.mjs.map} +1 -1
  55. package/dist/{chunk-CLTNCBSP.js → chunk-NSZN54HW.js} +4 -4
  56. package/dist/{chunk-CLTNCBSP.js.map → chunk-NSZN54HW.js.map} +1 -1
  57. package/dist/{chunk-7AM2SXEF.js → chunk-O4HH77A4.js} +85 -85
  58. package/dist/{chunk-7AM2SXEF.js.map → chunk-O4HH77A4.js.map} +1 -1
  59. package/dist/{chunk-RFUSH7WD.js → chunk-TSNKICPP.js} +10 -10
  60. package/dist/{chunk-RFUSH7WD.js.map → chunk-TSNKICPP.js.map} +1 -1
  61. package/dist/{chunk-ARLYOLSO.mjs → chunk-W6MBDTKF.mjs} +3 -3
  62. package/dist/{chunk-ARLYOLSO.mjs.map → chunk-W6MBDTKF.mjs.map} +1 -1
  63. package/dist/{chunk-IVKFXPLO.js → chunk-YSYEV2Z6.js} +28 -28
  64. package/dist/{chunk-IVKFXPLO.js.map → chunk-YSYEV2Z6.js.map} +1 -1
  65. package/dist/index.d.mts +108 -4
  66. package/dist/index.d.ts +108 -4
  67. package/dist/index.js +670 -662
  68. package/dist/index.mjs +1 -1
  69. package/dist/platform/admin/index.js +9 -9
  70. package/dist/platform/admin/index.mjs +3 -3
  71. package/dist/platform/agents-workspace.js +6 -6
  72. package/dist/platform/agents-workspace.mjs +5 -5
  73. package/dist/platform/app-shell.js +3 -3
  74. package/dist/platform/app-shell.mjs +2 -2
  75. package/dist/platform/auth/index.js +21 -21
  76. package/dist/platform/auth/index.mjs +3 -3
  77. package/dist/platform/billing/index.js +3 -3
  78. package/dist/platform/billing/index.mjs +2 -2
  79. package/dist/platform/impersonation/index.js +3 -3
  80. package/dist/platform/impersonation/index.mjs +2 -2
  81. package/dist/platform/index.js +74 -74
  82. package/dist/platform/index.mjs +17 -17
  83. package/dist/platform/pages/index.d.mts +235 -3
  84. package/dist/platform/pages/index.d.ts +235 -3
  85. package/dist/platform/pages/index.js +1959 -246
  86. package/dist/platform/pages/index.js.map +1 -1
  87. package/dist/platform/pages/index.mjs +1728 -17
  88. package/dist/platform/pages/index.mjs.map +1 -1
  89. package/dist/platform/settings/index.js +6 -6
  90. package/dist/platform/settings/index.mjs +5 -5
  91. package/dist/platform/workflow-canvas-shell.js +4 -4
  92. package/dist/platform/workflow-canvas-shell.mjs +3 -3
  93. package/package.json +1 -1
  94. package/dist/chunk-MT66VKLS.js.map +0 -1
  95. package/dist/chunk-ZQRUAXGP.mjs.map +0 -1
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import { adaptWorkflowGraphToUi, formatDurationMs } from '../../chunk-UQXVCVAN.mjs';
3
- import { WorkflowWorkspace } from '../../chunk-GQWC4EKE.mjs';
4
- export { RolesPageView, UsersPageView } from '../../chunk-GQWC4EKE.mjs';
5
- import { DatasourceModal, findCategory, DIALECT_CATEGORIES } from '../../chunk-6QJI5YOJ.mjs';
6
- export { DIALECT_CATEGORIES, DatasourceFormModal, DatasourceModal, findCategory, findDialect } from '../../chunk-6QJI5YOJ.mjs';
7
- import { defaultRuleForm, RuleForm, ExecutionTimelinePanel } from '../../chunk-AXBD6OAF.mjs';
3
+ import { WorkflowWorkspace } from '../../chunk-5U43K6G3.mjs';
4
+ export { RolesPageView, UsersPageView } from '../../chunk-5U43K6G3.mjs';
5
+ import { DatasourceModal, findDialect, findCategory, DIALECT_CATEGORIES } from '../../chunk-FD376DZ6.mjs';
6
+ export { DIALECT_CATEGORIES, DatasourceFormModal, DatasourceModal, findCategory, findDialect } from '../../chunk-FD376DZ6.mjs';
7
+ import { defaultRuleForm, RuleForm, ExecutionTimelinePanel, defaultRuleCondition, defaultRuleAction, RuleConditionBuilder, RuleActionBuilder } from '../../chunk-A256OE5E.mjs';
8
8
  import '../../chunk-JB6RNAD2.mjs';
9
9
  import '../../chunk-LEXBTVGM.mjs';
10
- import '../../chunk-EAIE4QGD.mjs';
11
- import { HeroSection, PageLoadingState, PageEmptyState, SearchBar, EntityCard, CreateActionButton, GlassModal, FormGrid, FormSelect, FormInput, FormTextarea, SectionHeader, Text, Form, FormActionsRow, Table, TableHead, TableRow, TableHeader, TableBody, TableCell, InlineForm, CopyableId, ListCard, ListCardItem, Avatar, SectionCard, Tabs, TabsList, TabsTrigger, TabsContent, StepTimeline, FilterTileButton } from '../../chunk-ZQRUAXGP.mjs';
10
+ import '../../chunk-DA3H7ERQ.mjs';
11
+ import { HeroSection, PageLoadingState, PageEmptyState, SearchBar, EntityCard, CreateActionButton, GlassModal, FormGrid, FormSelect, FormInput, FormTextarea, SectionHeader, Text, Form, FormActionsRow, Table, TableHead, TableRow, TableHeader, TableBody, TableCell, InlineForm, CopyableId, ListCard, ListCardItem, Avatar, SectionCard, Tabs, TabsList, TabsTrigger, TabsContent, StepTimeline, FilterTileButton, FormToggle, Spinner, StatusBadge, FormCheckbox, SegmentedControl, DatePicker, TimePicker } from '../../chunk-5KI7FB3E.mjs';
12
12
  import '../../chunk-7VJ7CMMT.mjs';
13
13
  import '../../chunk-RHRJXK5R.mjs';
14
14
  import '../../chunk-3AY5HIQ6.mjs';
@@ -18,7 +18,7 @@ import '../../chunk-D2JF6C3E.mjs';
18
18
  import { useLink } from '../../chunk-QWG2FMUN.mjs';
19
19
  import '../../chunk-G7JQ4OCE.mjs';
20
20
  import { useState, useMemo, useEffect, useCallback } from 'react';
21
- import { CubeTransparentIcon, CpuChipIcon, ChatBubbleLeftEllipsisIcon, WrenchScrewdriverIcon, AdjustmentsHorizontalIcon, CircleStackIcon, RectangleStackIcon, ClockIcon, LinkIcon, KeyIcon, ArrowPathIcon, TrashIcon, PlusIcon, PencilSquareIcon } from '@heroicons/react/24/outline';
21
+ import { CubeTransparentIcon, CpuChipIcon, ChatBubbleLeftEllipsisIcon, WrenchScrewdriverIcon, AdjustmentsHorizontalIcon, CircleStackIcon, RectangleStackIcon, ClockIcon, LinkIcon, KeyIcon, ArrowPathIcon, TrashIcon, PlusIcon, PencilSquareIcon, BellAlertIcon, GlobeAltIcon, PencilIcon, ArrowUpCircleIcon, SparklesIcon } from '@heroicons/react/24/outline';
22
22
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
23
 
24
24
  function AgentsModelsPageView({ labels, models, loading }) {
@@ -944,8 +944,12 @@ function setFromJson(set, key, raw) {
944
944
  set(key, raw);
945
945
  }
946
946
  }
947
- function RulesPageView({ labels, rules, loading, onCreate, onUpdate, onDelete }) {
947
+ function RulesPageView({ labels, rules, loading, onCreate, onUpdate, onDelete, onAddClick }) {
948
948
  const [createOpen, setCreateOpen] = useState(false);
949
+ const openCreate = () => {
950
+ if (onAddClick) onAddClick();
951
+ else setCreateOpen(true);
952
+ };
949
953
  const [editing, setEditing] = useState(null);
950
954
  const [searchTerm, setSearchTerm] = useState("");
951
955
  const allRules = rules;
@@ -964,7 +968,7 @@ function RulesPageView({ labels, rules, loading, onCreate, onUpdate, onDelete })
964
968
  {
965
969
  mode: "desktop",
966
970
  label: labels.addRule,
967
- onClick: () => setCreateOpen(true),
971
+ onClick: openCreate,
968
972
  accent: "fuchsia"
969
973
  }
970
974
  )
@@ -975,7 +979,7 @@ function RulesPageView({ labels, rules, loading, onCreate, onUpdate, onDelete })
975
979
  {
976
980
  mode: "mobile",
977
981
  label: labels.addRule,
978
- onClick: () => setCreateOpen(true),
982
+ onClick: openCreate,
979
983
  accent: "fuchsia"
980
984
  }
981
985
  );
@@ -1259,9 +1263,14 @@ function DatasourcesPageView({
1259
1263
  labels,
1260
1264
  datasources: externalDatasources,
1261
1265
  useSampleData = false,
1262
- onCreate
1266
+ onCreate,
1267
+ onAddClick
1263
1268
  }) {
1264
1269
  const [modalOpen, setModalOpen] = useState(false);
1270
+ const openCreate = () => {
1271
+ if (onAddClick) onAddClick();
1272
+ else setModalOpen(true);
1273
+ };
1265
1274
  const [searchTerm, setSearchTerm] = useState("");
1266
1275
  const [localDatasources, setLocalDatasources] = useState(
1267
1276
  useSampleData ? SAMPLE_DATASOURCES : []
@@ -1306,7 +1315,7 @@ function DatasourcesPageView({
1306
1315
  {
1307
1316
  mode: "desktop",
1308
1317
  label: labels.addDatasource,
1309
- onClick: () => setModalOpen(true),
1318
+ onClick: openCreate,
1310
1319
  accent: "amber"
1311
1320
  }
1312
1321
  )
@@ -1317,7 +1326,7 @@ function DatasourcesPageView({
1317
1326
  {
1318
1327
  mode: "mobile",
1319
1328
  label: labels.addDatasource,
1320
- onClick: () => setModalOpen(true),
1329
+ onClick: openCreate,
1321
1330
  accent: "amber"
1322
1331
  }
1323
1332
  ),
@@ -2820,14 +2829,14 @@ function RangeSliderField({
2820
2829
  step,
2821
2830
  zones,
2822
2831
  trackGradient,
2823
- formatValue,
2832
+ formatValue: formatValue2,
2824
2833
  ariaLabel
2825
2834
  }) {
2826
2835
  const percent = (value - min) / (max - min) * 100;
2827
2836
  const activeZone = zones?.find((z) => value <= z.max) ?? zones?.[zones.length - 1];
2828
2837
  const thumbColor = activeZone?.thumbColor ?? "#6366f1";
2829
2838
  const glow = hexToGlow(thumbColor);
2830
- const displayValue = formatValue ? formatValue(value) : value.toString();
2839
+ const displayValue = formatValue2 ? formatValue2(value) : value.toString();
2831
2840
  const ariaText = activeZone ? `${displayValue} \u2014 ${activeZone.label}` : displayValue;
2832
2841
  return /* @__PURE__ */ jsxs("div", { children: [
2833
2842
  /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
@@ -3616,7 +3625,1709 @@ function ReviewRow({ label, value }) {
3616
3625
  /* @__PURE__ */ jsx("dd", { className: "mt-0.5 truncate text-xs font-semibold text-gray-900 dark:text-white", children: value })
3617
3626
  ] });
3618
3627
  }
3628
+ var DIALECT_LOGO_SRC = {
3629
+ bigquery: "/logos/datasources/bigquery.svg",
3630
+ postgres: "/logos/datasources/postgres.svg",
3631
+ postgresql: "/logos/datasources/postgres.svg",
3632
+ mysql: "/logos/datasources/mysql.svg",
3633
+ mariadb: "/logos/datasources/mariadb.svg",
3634
+ snowflake: "/logos/datasources/snowflake.svg",
3635
+ mongodb: "/logos/datasources/mongodb.svg",
3636
+ redis: "/logos/datasources/redis.svg",
3637
+ clickhouse: "/logos/datasources/clickhouse.svg",
3638
+ elasticsearch: "/logos/datasources/elasticsearch.svg",
3639
+ duckdb: "/logos/datasources/duckdb.svg",
3640
+ sqlite: "/logos/datasources/sqlite.svg",
3641
+ oracle: "/logos/datasources/oracle.svg",
3642
+ mssql: "/logos/datasources/mssql.svg",
3643
+ sqlserver: "/logos/datasources/mssql.svg",
3644
+ cassandra: "/logos/datasources/cassandra.svg",
3645
+ dynamodb: "/logos/datasources/dynamodb.svg",
3646
+ cockroach: "/logos/datasources/cockroachdb.svg",
3647
+ cockroachdb: "/logos/datasources/cockroachdb.svg",
3648
+ supabase: "/logos/datasources/supabase.svg",
3649
+ firebase: "/logos/datasources/firebase.svg",
3650
+ neo4j: "/logos/datasources/neo4j.svg",
3651
+ neptune: "/logos/datasources/neptune.svg",
3652
+ timestream: "/logos/datasources/timestream.svg",
3653
+ opensearch: "/logos/datasources/opensearch.svg"
3654
+ };
3655
+ var CATEGORY_COLOR = {
3656
+ relational: "blue",
3657
+ nosql: "emerald",
3658
+ warehouse: "purple",
3659
+ timeseries: "sky",
3660
+ graph: "pink",
3661
+ keyvalue: "red",
3662
+ search: "amber"
3663
+ };
3664
+ var TOTAL_STEPS2 = 4;
3665
+ function DatasourceNewWizardPageView({
3666
+ labels,
3667
+ initialStep,
3668
+ onStepChange,
3669
+ onSubmit,
3670
+ onCancel,
3671
+ onTestConnection
3672
+ }) {
3673
+ const clampedInitial = Math.min(TOTAL_STEPS2, Math.max(1, initialStep ?? 1));
3674
+ const [step, setStep] = useState(clampedInitial);
3675
+ const [dialect, setDialect] = useState("");
3676
+ const [name, setName] = useState("");
3677
+ const [host, setHost] = useState("");
3678
+ const [port, setPort] = useState("");
3679
+ const [database, setDatabase] = useState("");
3680
+ const [username, setUsername] = useState("");
3681
+ const [password, setPassword] = useState("");
3682
+ const [schema, setSchema] = useState("");
3683
+ const [connectionString, setConnectionString] = useState("");
3684
+ const [projectId, setProjectId] = useState("");
3685
+ const [dataset, setDataset] = useState("");
3686
+ const [keyFile, setKeyFile] = useState("");
3687
+ const [account, setAccount] = useState("");
3688
+ const [warehouseField, setWarehouseField] = useState("");
3689
+ const [region, setRegion] = useState("");
3690
+ const [bucket, setBucket] = useState("");
3691
+ const [token, setToken] = useState("");
3692
+ const [apiKey, setApiKey] = useState("");
3693
+ const [environment, setEnvironment] = useState("");
3694
+ const [index, setIndex] = useState("");
3695
+ const [ssl, setSsl] = useState(true);
3696
+ const [readOnly, setReadOnly] = useState(true);
3697
+ const [maxPoolSize, setMaxPoolSize] = useState("5");
3698
+ const [timeoutMs, setTimeoutMs] = useState("5000");
3699
+ const [allowedTables, setAllowedTables] = useState("");
3700
+ const [blockedColumns, setBlockedColumns] = useState("");
3701
+ const [maskPii, setMaskPii] = useState(false);
3702
+ const [submitting, setSubmitting] = useState(false);
3703
+ const [touched, setTouched] = useState(false);
3704
+ const [testStatus, setTestStatus] = useState("idle");
3705
+ const dialectOption = useMemo(() => dialect ? findDialect(dialect) : null, [dialect]);
3706
+ const category = useMemo(() => dialect ? findCategory(dialect) : null, [dialect]);
3707
+ useEffect(() => {
3708
+ if (dialectOption?.defaultPort && (port === "" || /^[0-9]+$/.test(port))) {
3709
+ setPort(String(dialectOption.defaultPort));
3710
+ }
3711
+ }, [dialect]);
3712
+ useEffect(() => {
3713
+ const next = Math.min(TOTAL_STEPS2, Math.max(1, initialStep ?? 1));
3714
+ if (next !== step) setStep(next);
3715
+ }, [initialStep]);
3716
+ function markTouched() {
3717
+ if (!touched) setTouched(true);
3718
+ }
3719
+ const goToStep = useCallback((next) => {
3720
+ const clamped = Math.min(TOTAL_STEPS2, Math.max(1, next));
3721
+ setStep(clamped);
3722
+ onStepChange?.(clamped);
3723
+ }, [onStepChange]);
3724
+ function canAdvance(from) {
3725
+ if (from === 1) return Boolean(dialect);
3726
+ if (from === 2) return name.trim().length > 0;
3727
+ return true;
3728
+ }
3729
+ const goNext = useCallback(() => {
3730
+ if (!canAdvance(step)) return;
3731
+ if (step < TOTAL_STEPS2) goToStep(step + 1);
3732
+ }, [step, dialect, name]);
3733
+ const goBack = useCallback(() => {
3734
+ if (step > 1) goToStep(step - 1);
3735
+ }, [step, goToStep]);
3736
+ const cancelWithConfirm = useCallback(() => {
3737
+ if (touched && !window.confirm(labels.wizardCancelConfirm)) return;
3738
+ onCancel();
3739
+ }, [touched, labels.wizardCancelConfirm, onCancel]);
3740
+ function buildPayload() {
3741
+ const payload = {
3742
+ name: name.trim(),
3743
+ dialect,
3744
+ ssl,
3745
+ readOnly
3746
+ };
3747
+ if (host.trim()) payload.host = host.trim();
3748
+ const portNum = Number(port);
3749
+ if (Number.isFinite(portNum) && portNum > 0) payload.port = portNum;
3750
+ if (database.trim()) payload.database = database.trim();
3751
+ if (username.trim()) payload.username = username.trim();
3752
+ if (password) payload.password = password;
3753
+ if (schema.trim()) payload.schema = schema.trim();
3754
+ if (connectionString.trim()) payload.connectionString = connectionString.trim();
3755
+ if (projectId.trim()) payload.projectId = projectId.trim();
3756
+ if (dataset.trim()) payload.dataset = dataset.trim();
3757
+ if (keyFile.trim()) payload.keyFile = keyFile.trim();
3758
+ if (account.trim()) payload.account = account.trim();
3759
+ if (warehouseField.trim()) payload.warehouse = warehouseField.trim();
3760
+ if (region.trim()) payload.region = region.trim();
3761
+ if (bucket.trim()) payload.bucket = bucket.trim();
3762
+ if (token) payload.token = token;
3763
+ if (apiKey) payload.apiKey = apiKey;
3764
+ if (environment.trim()) payload.environment = environment.trim();
3765
+ if (index.trim()) payload.index = index.trim();
3766
+ const pool = Number(maxPoolSize);
3767
+ if (Number.isFinite(pool) && pool > 0) payload.maxPoolSize = pool;
3768
+ const timeout = Number(timeoutMs);
3769
+ if (Number.isFinite(timeout) && timeout > 0) payload.timeoutMs = timeout;
3770
+ const allowed = splitList(allowedTables);
3771
+ if (allowed.length > 0) payload.allowedTables = allowed;
3772
+ const blocked = splitList(blockedColumns);
3773
+ if (blocked.length > 0) payload.blockedColumns = blocked;
3774
+ return payload;
3775
+ }
3776
+ async function handleTestConnection() {
3777
+ setTestStatus("testing");
3778
+ try {
3779
+ const ok = onTestConnection ? await onTestConnection(buildPayload()) : await simulateTest();
3780
+ setTestStatus(ok ? "success" : "failed");
3781
+ setTimeout(() => setTestStatus("idle"), 3500);
3782
+ } catch {
3783
+ setTestStatus("failed");
3784
+ setTimeout(() => setTestStatus("idle"), 3500);
3785
+ }
3786
+ }
3787
+ async function submit() {
3788
+ setSubmitting(true);
3789
+ try {
3790
+ const payload = {
3791
+ ...buildPayload(),
3792
+ ...maskPii ? { maskPii: true } : {}
3793
+ };
3794
+ await onSubmit(payload);
3795
+ } finally {
3796
+ setSubmitting(false);
3797
+ }
3798
+ }
3799
+ useEffect(() => {
3800
+ function onKey(e) {
3801
+ if (e.key === "Escape") {
3802
+ e.preventDefault();
3803
+ cancelWithConfirm();
3804
+ return;
3805
+ }
3806
+ if (e.key === "Enter") {
3807
+ const target = e.target;
3808
+ const tag = target?.tagName?.toLowerCase();
3809
+ if (tag === "textarea" || tag === "select" || tag === "input" || tag === "button") return;
3810
+ e.preventDefault();
3811
+ if (step < TOTAL_STEPS2) goNext();
3812
+ else void submit();
3813
+ }
3814
+ }
3815
+ window.addEventListener("keydown", onKey);
3816
+ return () => window.removeEventListener("keydown", onKey);
3817
+ }, [step, dialect, name, touched]);
3818
+ const stepTitles = [
3819
+ labels.wizardStep1Title,
3820
+ labels.wizardStep2Title,
3821
+ labels.wizardStep3Title,
3822
+ labels.wizardStep4Title
3823
+ ];
3824
+ const stepSubtitles = [
3825
+ labels.wizardStep1Subtitle,
3826
+ labels.wizardStep2Subtitle,
3827
+ labels.wizardStep3Subtitle,
3828
+ labels.wizardStep4Subtitle
3829
+ ];
3830
+ const timelineSteps = stepTitles.map((title, idx) => ({
3831
+ id: String(idx + 1),
3832
+ name: title,
3833
+ description: stepSubtitles[idx],
3834
+ status: idx + 1 < step ? "complete" : idx + 1 === step ? "current" : "upcoming"
3835
+ }));
3836
+ const counter = labels.wizardStepCounter.replace("{current}", String(step)).replace("{total}", String(TOTAL_STEPS2));
3837
+ const hero = /* @__PURE__ */ jsx(
3838
+ HeroSection,
3839
+ {
3840
+ icon: /* @__PURE__ */ jsx(CircleStackIcon, { className: "h-5 w-5" }),
3841
+ label: counter,
3842
+ title: labels.pageTitle,
3843
+ subtitle: stepSubtitles[step - 1] ?? labels.pageSubtitle,
3844
+ gradient: category?.gradient ?? "from-amber-500 to-orange-600"
3845
+ }
3846
+ );
3847
+ function renderStep1() {
3848
+ return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: DIALECT_CATEGORIES.map((cat) => {
3849
+ const color = CATEGORY_COLOR[cat.id] ?? "slate";
3850
+ const categoryLabel = labels[cat.labelKey] ?? cat.id;
3851
+ return /* @__PURE__ */ jsx(
3852
+ SectionCard,
3853
+ {
3854
+ variant: "glass",
3855
+ header: {
3856
+ title: categoryLabel,
3857
+ icon: /* @__PURE__ */ jsx(cat.icon, { className: "h-4 w-4" }),
3858
+ gradient: cat.gradient
3859
+ },
3860
+ children: /* @__PURE__ */ jsx(
3861
+ "div",
3862
+ {
3863
+ role: "radiogroup",
3864
+ "aria-label": categoryLabel,
3865
+ className: "grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4",
3866
+ children: cat.dialects.map((opt) => {
3867
+ const selected = opt.value === dialect;
3868
+ const logoSrc = DIALECT_LOGO_SRC[opt.value.toLowerCase()];
3869
+ return /* @__PURE__ */ jsx(
3870
+ FilterTileButton,
3871
+ {
3872
+ isActive: selected,
3873
+ color,
3874
+ icon: logoSrc ? /* @__PURE__ */ jsx("img", { src: logoSrc, alt: opt.label, className: "h-5 w-5 object-contain" }) : /* @__PURE__ */ jsx(CircleStackIcon, { className: "h-5 w-5" }),
3875
+ label: opt.label,
3876
+ count: opt.formType.replace("-", " "),
3877
+ onClick: () => {
3878
+ setDialect(opt.value);
3879
+ markTouched();
3880
+ }
3881
+ },
3882
+ opt.value
3883
+ );
3884
+ })
3885
+ }
3886
+ )
3887
+ },
3888
+ cat.id
3889
+ );
3890
+ }) });
3891
+ }
3892
+ function renderConnectionFields() {
3893
+ if (!dialectOption) return null;
3894
+ switch (dialectOption.formType) {
3895
+ case "standard":
3896
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3897
+ /* @__PURE__ */ jsx(
3898
+ FormInput,
3899
+ {
3900
+ label: labels.fieldHost,
3901
+ value: host,
3902
+ onValueChange: (v) => {
3903
+ setHost(v);
3904
+ markTouched();
3905
+ },
3906
+ placeholder: labels.fieldHostPlaceholder,
3907
+ required: true
3908
+ }
3909
+ ),
3910
+ /* @__PURE__ */ jsx(
3911
+ FormInput,
3912
+ {
3913
+ label: labels.fieldPort,
3914
+ type: "number",
3915
+ value: port,
3916
+ onValueChange: (v) => {
3917
+ setPort(v);
3918
+ markTouched();
3919
+ }
3920
+ }
3921
+ ),
3922
+ /* @__PURE__ */ jsx(
3923
+ FormInput,
3924
+ {
3925
+ label: labels.fieldDatabase,
3926
+ value: database,
3927
+ onValueChange: (v) => {
3928
+ setDatabase(v);
3929
+ markTouched();
3930
+ },
3931
+ placeholder: labels.fieldDatabasePlaceholder,
3932
+ required: true
3933
+ }
3934
+ ),
3935
+ /* @__PURE__ */ jsx(
3936
+ FormInput,
3937
+ {
3938
+ label: labels.fieldUsername,
3939
+ value: username,
3940
+ onValueChange: (v) => {
3941
+ setUsername(v);
3942
+ markTouched();
3943
+ },
3944
+ placeholder: labels.fieldUsernamePlaceholder
3945
+ }
3946
+ ),
3947
+ /* @__PURE__ */ jsx(
3948
+ FormInput,
3949
+ {
3950
+ label: labels.fieldPassword,
3951
+ type: "password",
3952
+ value: password,
3953
+ onValueChange: (v) => {
3954
+ setPassword(v);
3955
+ markTouched();
3956
+ },
3957
+ placeholder: labels.fieldPasswordPlaceholder
3958
+ }
3959
+ ),
3960
+ /* @__PURE__ */ jsx(
3961
+ FormInput,
3962
+ {
3963
+ label: labels.fieldSchema,
3964
+ value: schema,
3965
+ onValueChange: (v) => {
3966
+ setSchema(v);
3967
+ markTouched();
3968
+ },
3969
+ placeholder: labels.fieldSchemaPlaceholder
3970
+ }
3971
+ )
3972
+ ] });
3973
+ case "connection-string":
3974
+ return /* @__PURE__ */ jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsx(
3975
+ FormInput,
3976
+ {
3977
+ label: labels.fieldConnectionString,
3978
+ value: connectionString,
3979
+ onValueChange: (v) => {
3980
+ setConnectionString(v);
3981
+ markTouched();
3982
+ },
3983
+ placeholder: labels.fieldConnectionStringPlaceholder,
3984
+ required: true
3985
+ }
3986
+ ) });
3987
+ case "cloud-bigquery":
3988
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3989
+ /* @__PURE__ */ jsx(
3990
+ FormInput,
3991
+ {
3992
+ label: labels.fieldProjectId,
3993
+ value: projectId,
3994
+ onValueChange: (v) => {
3995
+ setProjectId(v);
3996
+ markTouched();
3997
+ },
3998
+ placeholder: labels.fieldProjectIdPlaceholder,
3999
+ required: true
4000
+ }
4001
+ ),
4002
+ /* @__PURE__ */ jsx(
4003
+ FormInput,
4004
+ {
4005
+ label: labels.fieldDataset,
4006
+ value: dataset,
4007
+ onValueChange: (v) => {
4008
+ setDataset(v);
4009
+ markTouched();
4010
+ },
4011
+ placeholder: labels.fieldDatasetPlaceholder,
4012
+ required: true
4013
+ }
4014
+ ),
4015
+ /* @__PURE__ */ jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsx(
4016
+ FormInput,
4017
+ {
4018
+ label: labels.fieldKeyFile,
4019
+ value: keyFile,
4020
+ onValueChange: (v) => {
4021
+ setKeyFile(v);
4022
+ markTouched();
4023
+ },
4024
+ placeholder: labels.fieldKeyFilePlaceholder
4025
+ }
4026
+ ) })
4027
+ ] });
4028
+ case "cloud-snowflake":
4029
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4030
+ /* @__PURE__ */ jsx(
4031
+ FormInput,
4032
+ {
4033
+ label: labels.fieldAccount,
4034
+ value: account,
4035
+ onValueChange: (v) => {
4036
+ setAccount(v);
4037
+ markTouched();
4038
+ },
4039
+ placeholder: labels.fieldAccountPlaceholder,
4040
+ required: true
4041
+ }
4042
+ ),
4043
+ /* @__PURE__ */ jsx(
4044
+ FormInput,
4045
+ {
4046
+ label: labels.fieldWarehouse,
4047
+ value: warehouseField,
4048
+ onValueChange: (v) => {
4049
+ setWarehouseField(v);
4050
+ markTouched();
4051
+ },
4052
+ placeholder: labels.fieldWarehousePlaceholder,
4053
+ required: true
4054
+ }
4055
+ ),
4056
+ /* @__PURE__ */ jsx(
4057
+ FormInput,
4058
+ {
4059
+ label: labels.fieldDatabase,
4060
+ value: database,
4061
+ onValueChange: (v) => {
4062
+ setDatabase(v);
4063
+ markTouched();
4064
+ },
4065
+ placeholder: labels.fieldDatabasePlaceholder,
4066
+ required: true
4067
+ }
4068
+ ),
4069
+ /* @__PURE__ */ jsx(
4070
+ FormInput,
4071
+ {
4072
+ label: labels.fieldUsername,
4073
+ value: username,
4074
+ onValueChange: (v) => {
4075
+ setUsername(v);
4076
+ markTouched();
4077
+ },
4078
+ placeholder: labels.fieldUsernamePlaceholder,
4079
+ required: true
4080
+ }
4081
+ ),
4082
+ /* @__PURE__ */ jsx(
4083
+ FormInput,
4084
+ {
4085
+ label: labels.fieldPassword,
4086
+ type: "password",
4087
+ value: password,
4088
+ onValueChange: (v) => {
4089
+ setPassword(v);
4090
+ markTouched();
4091
+ },
4092
+ placeholder: labels.fieldPasswordPlaceholder
4093
+ }
4094
+ ),
4095
+ /* @__PURE__ */ jsx(
4096
+ FormInput,
4097
+ {
4098
+ label: labels.fieldSchema,
4099
+ value: schema,
4100
+ onValueChange: (v) => {
4101
+ setSchema(v);
4102
+ markTouched();
4103
+ },
4104
+ placeholder: labels.fieldSchemaPlaceholder
4105
+ }
4106
+ )
4107
+ ] });
4108
+ case "cloud-key":
4109
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4110
+ /* @__PURE__ */ jsx(
4111
+ FormInput,
4112
+ {
4113
+ label: labels.fieldRegion,
4114
+ value: region,
4115
+ onValueChange: (v) => {
4116
+ setRegion(v);
4117
+ markTouched();
4118
+ },
4119
+ placeholder: labels.fieldRegionPlaceholder,
4120
+ required: true
4121
+ }
4122
+ ),
4123
+ /* @__PURE__ */ jsx(
4124
+ FormInput,
4125
+ {
4126
+ label: labels.fieldToken,
4127
+ type: "password",
4128
+ value: token,
4129
+ onValueChange: (v) => {
4130
+ setToken(v);
4131
+ markTouched();
4132
+ },
4133
+ placeholder: labels.fieldTokenPlaceholder,
4134
+ required: true
4135
+ }
4136
+ ),
4137
+ /* @__PURE__ */ jsx(
4138
+ FormInput,
4139
+ {
4140
+ label: labels.fieldBucket,
4141
+ value: bucket,
4142
+ onValueChange: (v) => {
4143
+ setBucket(v);
4144
+ markTouched();
4145
+ },
4146
+ placeholder: labels.fieldBucketPlaceholder
4147
+ }
4148
+ )
4149
+ ] });
4150
+ case "vector-key":
4151
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4152
+ /* @__PURE__ */ jsx(
4153
+ FormInput,
4154
+ {
4155
+ label: labels.fieldApiKey,
4156
+ type: "password",
4157
+ value: apiKey,
4158
+ onValueChange: (v) => {
4159
+ setApiKey(v);
4160
+ markTouched();
4161
+ },
4162
+ placeholder: labels.fieldApiKeyPlaceholder,
4163
+ required: true
4164
+ }
4165
+ ),
4166
+ /* @__PURE__ */ jsx(
4167
+ FormInput,
4168
+ {
4169
+ label: labels.fieldEnvironment,
4170
+ value: environment,
4171
+ onValueChange: (v) => {
4172
+ setEnvironment(v);
4173
+ markTouched();
4174
+ },
4175
+ placeholder: labels.fieldEnvironmentPlaceholder,
4176
+ required: true
4177
+ }
4178
+ ),
4179
+ /* @__PURE__ */ jsx(
4180
+ FormInput,
4181
+ {
4182
+ label: labels.fieldIndex,
4183
+ value: index,
4184
+ onValueChange: (v) => {
4185
+ setIndex(v);
4186
+ markTouched();
4187
+ },
4188
+ placeholder: labels.fieldIndexPlaceholder
4189
+ }
4190
+ )
4191
+ ] });
4192
+ }
4193
+ }
4194
+ function renderStep2() {
4195
+ if (!dialectOption) {
4196
+ return /* @__PURE__ */ jsxs(SectionCard, { variant: "glass", header: { title: labels.wizardStep1Title }, children: [
4197
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-700 dark:text-slate-200", children: labels.wizardStep1Subtitle }),
4198
+ /* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsx(Button, { type: "button", outline: true, onClick: () => goToStep(1), children: labels.wizardBack }) })
4199
+ ] });
4200
+ }
4201
+ return /* @__PURE__ */ jsx(
4202
+ SectionCard,
4203
+ {
4204
+ variant: "glass",
4205
+ header: {
4206
+ title: dialectOption.label,
4207
+ subtitle: labels.wizardStep2Subtitle,
4208
+ icon: category?.icon ? /* @__PURE__ */ jsx(category.icon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(CircleStackIcon, { className: "h-4 w-4" }),
4209
+ gradient: category?.gradient
4210
+ },
4211
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4212
+ /* @__PURE__ */ jsx(
4213
+ FormInput,
4214
+ {
4215
+ label: labels.fieldName,
4216
+ value: name,
4217
+ onValueChange: (v) => {
4218
+ setName(v);
4219
+ markTouched();
4220
+ },
4221
+ placeholder: labels.fieldNamePlaceholder,
4222
+ required: true
4223
+ }
4224
+ ),
4225
+ /* @__PURE__ */ jsx(FormGrid, { children: renderConnectionFields() }),
4226
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-6 pt-1", children: [
4227
+ /* @__PURE__ */ jsx(
4228
+ FormToggle,
4229
+ {
4230
+ checked: ssl,
4231
+ onChange: (v) => {
4232
+ setSsl(v);
4233
+ markTouched();
4234
+ },
4235
+ label: labels.fieldSsl,
4236
+ variant: "inline"
4237
+ }
4238
+ ),
4239
+ /* @__PURE__ */ jsx(
4240
+ FormToggle,
4241
+ {
4242
+ checked: readOnly,
4243
+ onChange: (v) => {
4244
+ setReadOnly(v);
4245
+ markTouched();
4246
+ },
4247
+ label: labels.fieldReadOnly,
4248
+ variant: "inline"
4249
+ }
4250
+ )
4251
+ ] }),
4252
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: labels.fieldReadOnlyHelp }),
4253
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 border-t border-slate-200/60 pt-4 dark:border-white/10", children: [
4254
+ /* @__PURE__ */ jsx(
4255
+ Button,
4256
+ {
4257
+ type: "button",
4258
+ outline: true,
4259
+ onClick: () => void handleTestConnection(),
4260
+ disabled: testStatus === "testing",
4261
+ children: testStatus === "testing" ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
4262
+ /* @__PURE__ */ jsx(Spinner, { size: "xs" }),
4263
+ labels.testing
4264
+ ] }) : labels.testConnection
4265
+ }
4266
+ ),
4267
+ testStatus === "success" && /* @__PURE__ */ jsx(StatusBadge, { status: "success", label: labels.connectionSuccess }),
4268
+ testStatus === "failed" && /* @__PURE__ */ jsx(StatusBadge, { status: "error", label: labels.connectionFailed })
4269
+ ] })
4270
+ ] })
4271
+ }
4272
+ );
4273
+ }
4274
+ function renderStep3() {
4275
+ return /* @__PURE__ */ jsx(
4276
+ SectionCard,
4277
+ {
4278
+ variant: "glass",
4279
+ header: {
4280
+ title: labels.governanceSectionTitle,
4281
+ subtitle: labels.governanceSectionSubtitle
4282
+ },
4283
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4284
+ /* @__PURE__ */ jsxs(FormGrid, { children: [
4285
+ /* @__PURE__ */ jsx(
4286
+ FormInput,
4287
+ {
4288
+ label: labels.fieldMaxPoolSize,
4289
+ type: "number",
4290
+ min: 1,
4291
+ max: 100,
4292
+ value: maxPoolSize,
4293
+ onValueChange: (v) => {
4294
+ setMaxPoolSize(v);
4295
+ markTouched();
4296
+ },
4297
+ hint: labels.fieldMaxPoolSizeHint
4298
+ }
4299
+ ),
4300
+ /* @__PURE__ */ jsx(
4301
+ FormInput,
4302
+ {
4303
+ label: labels.fieldTimeoutMs,
4304
+ type: "number",
4305
+ min: 100,
4306
+ value: timeoutMs,
4307
+ onValueChange: (v) => {
4308
+ setTimeoutMs(v);
4309
+ markTouched();
4310
+ },
4311
+ hint: labels.fieldTimeoutMsHint
4312
+ }
4313
+ )
4314
+ ] }),
4315
+ /* @__PURE__ */ jsx(
4316
+ FormInput,
4317
+ {
4318
+ label: labels.fieldAllowedTables,
4319
+ value: allowedTables,
4320
+ onValueChange: (v) => {
4321
+ setAllowedTables(v);
4322
+ markTouched();
4323
+ },
4324
+ placeholder: labels.fieldAllowedTablesPlaceholder,
4325
+ hint: labels.fieldAllowedTablesHint
4326
+ }
4327
+ ),
4328
+ /* @__PURE__ */ jsx(
4329
+ FormInput,
4330
+ {
4331
+ label: labels.fieldBlockedColumns,
4332
+ value: blockedColumns,
4333
+ onValueChange: (v) => {
4334
+ setBlockedColumns(v);
4335
+ markTouched();
4336
+ },
4337
+ placeholder: labels.fieldBlockedColumnsPlaceholder,
4338
+ hint: labels.fieldBlockedColumnsHint
4339
+ }
4340
+ ),
4341
+ /* @__PURE__ */ jsx(
4342
+ FormCheckbox,
4343
+ {
4344
+ checked: maskPii,
4345
+ onChange: (v) => {
4346
+ setMaskPii(v);
4347
+ markTouched();
4348
+ },
4349
+ label: labels.fieldMaskPii,
4350
+ description: labels.fieldMaskPiiDescription
4351
+ }
4352
+ )
4353
+ ] })
4354
+ }
4355
+ );
4356
+ }
4357
+ function renderStep4() {
4358
+ const categoryLabel = category ? labels[category.labelKey] ?? category.id : labels.reviewNoneValue;
4359
+ const dialectLabel = dialectOption?.label ?? labels.reviewNoneValue;
4360
+ const allowed = splitList(allowedTables);
4361
+ const blocked = splitList(blockedColumns);
4362
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4363
+ /* @__PURE__ */ jsx(
4364
+ SectionCard,
4365
+ {
4366
+ variant: "glass",
4367
+ header: {
4368
+ title: labels.wizardStep1Title,
4369
+ subtitle: labels.wizardStep1Subtitle
4370
+ },
4371
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(1), children: [
4372
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
4373
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
4374
+ ] }),
4375
+ children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
4376
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewCategoryLabel, value: categoryLabel }),
4377
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewDialectLabel, value: dialectLabel })
4378
+ ] })
4379
+ }
4380
+ ),
4381
+ /* @__PURE__ */ jsx(
4382
+ SectionCard,
4383
+ {
4384
+ variant: "glass",
4385
+ header: {
4386
+ title: labels.wizardStep2Title,
4387
+ subtitle: labels.wizardStep2Subtitle
4388
+ },
4389
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(2), children: [
4390
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
4391
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
4392
+ ] }),
4393
+ children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
4394
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewNameLabel, value: name || labels.reviewNoneValue }),
4395
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewCredentialsLabel, value: labels.reviewCredentialsRedacted }),
4396
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewSslLabel, value: ssl ? labels.reviewYes : labels.reviewNo }),
4397
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewReadOnlyLabel, value: readOnly ? labels.reviewYes : labels.reviewNo })
4398
+ ] })
4399
+ }
4400
+ ),
4401
+ /* @__PURE__ */ jsx(
4402
+ SectionCard,
4403
+ {
4404
+ variant: "glass",
4405
+ header: {
4406
+ title: labels.wizardStep3Title,
4407
+ subtitle: labels.wizardStep3Subtitle
4408
+ },
4409
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(3), children: [
4410
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
4411
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
4412
+ ] }),
4413
+ children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
4414
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewPoolLabel, value: maxPoolSize || labels.reviewNoneValue }),
4415
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewTimeoutLabel, value: timeoutMs ? `${timeoutMs}ms` : labels.reviewNoneValue }),
4416
+ /* @__PURE__ */ jsx(
4417
+ ReviewRow2,
4418
+ {
4419
+ label: labels.reviewAllowedTablesLabel,
4420
+ value: allowed.length > 0 ? allowed.join(", ") : labels.reviewNoneValue
4421
+ }
4422
+ ),
4423
+ /* @__PURE__ */ jsx(
4424
+ ReviewRow2,
4425
+ {
4426
+ label: labels.reviewBlockedColumnsLabel,
4427
+ value: blocked.length > 0 ? blocked.join(", ") : labels.reviewNoneValue
4428
+ }
4429
+ ),
4430
+ /* @__PURE__ */ jsx(ReviewRow2, { label: labels.reviewMaskPiiLabel, value: maskPii ? labels.reviewYes : labels.reviewNo })
4431
+ ] })
4432
+ }
4433
+ )
4434
+ ] });
4435
+ }
4436
+ const stepBody = step === 1 ? renderStep1() : step === 2 ? renderStep2() : step === 3 ? renderStep3() : renderStep4();
4437
+ const advanceDisabled = !canAdvance(step);
4438
+ const footer = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-t border-slate-200/60 pt-4 dark:border-white/10", children: [
4439
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(Button, { type: "button", outline: true, onClick: goBack, disabled: step === 1 || submitting, children: labels.wizardBack }) }),
4440
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4441
+ /* @__PURE__ */ jsx(Button, { type: "button", outline: true, onClick: cancelWithConfirm, disabled: submitting, children: labels.wizardCancel }),
4442
+ step < TOTAL_STEPS2 ? /* @__PURE__ */ jsx(Button, { type: "button", color: "amber", onClick: goNext, disabled: advanceDisabled || submitting, children: labels.wizardNext }) : /* @__PURE__ */ jsx(Button, { type: "button", color: "amber", onClick: () => void submit(), disabled: submitting || !dialect || !name.trim(), children: submitting ? labels.wizardCreate + "\u2026" : labels.wizardCreate })
4443
+ ] })
4444
+ ] });
4445
+ const content = /* @__PURE__ */ jsxs(
4446
+ "form",
4447
+ {
4448
+ onSubmit: (e) => {
4449
+ e.preventDefault();
4450
+ if (step < TOTAL_STEPS2) goNext();
4451
+ else void submit();
4452
+ },
4453
+ className: "space-y-5",
4454
+ children: [
4455
+ /* @__PURE__ */ jsx(
4456
+ StepTimeline,
4457
+ {
4458
+ steps: timelineSteps,
4459
+ progressLabel: labels.pageTitle,
4460
+ onStepClick: (idx) => goToStep(idx + 1)
4461
+ }
4462
+ ),
4463
+ /* @__PURE__ */ jsxs("div", { className: "w-full space-y-5", children: [
4464
+ stepBody,
4465
+ footer
4466
+ ] })
4467
+ ]
4468
+ }
4469
+ );
4470
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4471
+ hero,
4472
+ content
4473
+ ] });
4474
+ }
4475
+ function ReviewRow2({ label, value }) {
4476
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-slate-200/60 bg-white/40 px-3 py-2 dark:border-white/10 dark:bg-white/[0.04]", children: [
4477
+ /* @__PURE__ */ jsx("dt", { className: "text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500", children: label }),
4478
+ /* @__PURE__ */ jsx("dd", { className: "mt-0.5 truncate text-xs font-semibold text-gray-900 dark:text-white", children: value })
4479
+ ] });
4480
+ }
4481
+ function splitList(raw) {
4482
+ return raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
4483
+ }
4484
+ async function simulateTest() {
4485
+ await new Promise((r) => setTimeout(r, 1500));
4486
+ return true;
4487
+ }
4488
+ function RangeSliderField2({
4489
+ sliderId,
4490
+ label,
4491
+ value,
4492
+ onChange,
4493
+ min,
4494
+ max,
4495
+ step,
4496
+ zones,
4497
+ trackGradient,
4498
+ formatValue: formatValue2,
4499
+ ariaLabel
4500
+ }) {
4501
+ const percent = (value - min) / (max - min) * 100;
4502
+ const activeZone = zones?.find((z) => value <= z.max) ?? zones?.[zones.length - 1];
4503
+ const thumbColor = activeZone?.thumbColor ?? "#6366f1";
4504
+ const glow = hexToGlow2(thumbColor);
4505
+ const displayValue = formatValue2 ? formatValue2(value) : value.toString();
4506
+ const ariaText = activeZone ? `${displayValue} \u2014 ${activeZone.label}` : displayValue;
4507
+ return /* @__PURE__ */ jsxs("div", { children: [
4508
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
4509
+ /* @__PURE__ */ jsx("label", { htmlFor: sliderId, className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: label }),
4510
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-bold tabular-nums text-gray-900 dark:text-white", children: displayValue })
4511
+ ] }),
4512
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
4513
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-1/2 h-2 -translate-y-1/2 overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700", children: /* @__PURE__ */ jsx(
4514
+ "div",
4515
+ {
4516
+ className: "h-full rounded-full transition-all duration-300 ease-out motion-reduce:transition-none",
4517
+ style: {
4518
+ width: `${Math.max(0, Math.min(100, percent))}%`,
4519
+ background: trackGradient ?? `linear-gradient(90deg, ${thumbColor}, ${thumbColor})`
4520
+ }
4521
+ }
4522
+ ) }),
4523
+ /* @__PURE__ */ jsx(
4524
+ "input",
4525
+ {
4526
+ id: sliderId,
4527
+ "data-slider-id": sliderId,
4528
+ type: "range",
4529
+ min,
4530
+ max,
4531
+ step,
4532
+ value,
4533
+ onChange: (e) => onChange(parseFloat(e.target.value)),
4534
+ "aria-label": ariaLabel ?? label,
4535
+ "aria-valuemin": min,
4536
+ "aria-valuemax": max,
4537
+ "aria-valuenow": value,
4538
+ "aria-valuetext": ariaText,
4539
+ className: "relative z-10 h-5 w-full cursor-pointer appearance-none bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:shadow-lg dark:[&::-webkit-slider-thumb]:border-gray-900"
4540
+ }
4541
+ ),
4542
+ /* @__PURE__ */ jsx("style", { children: `[data-slider-id="${sliderId}"]::-webkit-slider-thumb { background: ${thumbColor}; box-shadow: 0 0 8px ${glow}; } [data-slider-id="${sliderId}"]::-moz-range-thumb { background: ${thumbColor}; border: 2px solid white; box-shadow: 0 0 8px ${glow}; }` })
4543
+ ] }),
4544
+ zones && zones.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-1 flex items-center justify-between", children: zones.map((z) => {
4545
+ const isActive = z.label === activeZone?.label;
4546
+ return /* @__PURE__ */ jsx(
4547
+ "span",
4548
+ {
4549
+ className: `text-[10px] font-medium transition-colors motion-reduce:transition-none ${isActive ? z.color : "text-gray-400 dark:text-gray-500"}`,
4550
+ children: z.label
4551
+ },
4552
+ z.label
4553
+ );
4554
+ }) })
4555
+ ] });
4556
+ }
4557
+ function hexToGlow2(hex) {
4558
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex);
4559
+ if (!m) return "rgba(99,102,241,0.5)";
4560
+ const int = parseInt(m[1], 16);
4561
+ const r = int >> 16 & 255;
4562
+ const g = int >> 8 & 255;
4563
+ const b = int & 255;
4564
+ return `rgba(${r},${g},${b},0.5)`;
4565
+ }
4566
+ var ACTION_TILES = [
4567
+ { id: "notify", color: "sky", icon: BellAlertIcon, labelKey: "actionNotifyLabel", descriptionKey: "actionNotifyDescription" },
4568
+ { id: "call-webhook", color: "indigo", icon: GlobeAltIcon, labelKey: "actionWebhookLabel", descriptionKey: "actionWebhookDescription" },
4569
+ { id: "mutate", color: "amber", icon: PencilIcon, labelKey: "actionMutateLabel", descriptionKey: "actionMutateDescription" },
4570
+ { id: "escalate", color: "rose", icon: ArrowUpCircleIcon, labelKey: "actionEscalateLabel", descriptionKey: "actionEscalateDescription" },
4571
+ { id: "route-to-agent", color: "violet", icon: SparklesIcon, labelKey: "actionRouteLabel", descriptionKey: "actionRouteDescription" }
4572
+ ];
4573
+ var WEEKDAYS = [
4574
+ { id: "mon", labelKey: "weekdayMon" },
4575
+ { id: "tue", labelKey: "weekdayTue" },
4576
+ { id: "wed", labelKey: "weekdayWed" },
4577
+ { id: "thu", labelKey: "weekdayThu" },
4578
+ { id: "fri", labelKey: "weekdayFri" },
4579
+ { id: "sat", labelKey: "weekdaySat" },
4580
+ { id: "sun", labelKey: "weekdaySun" }
4581
+ ];
4582
+ var TOTAL_STEPS3 = 5;
4583
+ function RuleNewWizardPageView({
4584
+ labels,
4585
+ initialStep,
4586
+ onStepChange,
4587
+ onSubmit,
4588
+ onCancel
4589
+ }) {
4590
+ const clampedInitial = Math.min(TOTAL_STEPS3, Math.max(1, initialStep ?? 1));
4591
+ const [step, setStep] = useState(clampedInitial);
4592
+ const [name, setName] = useState("");
4593
+ const [description, setDescription] = useState("");
4594
+ const [priority, setPriority] = useState(50);
4595
+ const [enabled, setEnabled] = useState(true);
4596
+ const [status, setStatus] = useState("active");
4597
+ const [tagsInput, setTagsInput] = useState("");
4598
+ const [combinator, setCombinator] = useState("and");
4599
+ const [condition, setCondition] = useState(defaultRuleCondition());
4600
+ const [actionTileId, setActionTileId] = useState("");
4601
+ const [action, setAction] = useState(defaultRuleAction());
4602
+ const [validFromDate, setValidFromDate] = useState(null);
4603
+ const [validFromTime, setValidFromTime] = useState(null);
4604
+ const [validUntilDate, setValidUntilDate] = useState(null);
4605
+ const [validUntilTime, setValidUntilTime] = useState(null);
4606
+ const [noExpiry, setNoExpiry] = useState(true);
4607
+ const [recurrence, setRecurrence] = useState("one-off");
4608
+ const [cronExpression, setCronExpression] = useState("");
4609
+ const [weekdays, setWeekdays] = useState([]);
4610
+ const [recurringTime, setRecurringTime] = useState(null);
4611
+ const [submitting, setSubmitting] = useState(false);
4612
+ const [touched, setTouched] = useState(false);
4613
+ function markTouched() {
4614
+ if (!touched) setTouched(true);
4615
+ }
4616
+ useEffect(() => {
4617
+ const next = Math.min(TOTAL_STEPS3, Math.max(1, initialStep ?? 1));
4618
+ if (next !== step) setStep(next);
4619
+ }, [initialStep]);
4620
+ const goToStep = useCallback((next) => {
4621
+ const clamped = Math.min(TOTAL_STEPS3, Math.max(1, next));
4622
+ setStep(clamped);
4623
+ onStepChange?.(clamped);
4624
+ }, [onStepChange]);
4625
+ function canAdvance(from) {
4626
+ if (from === 1) return name.trim().length > 0;
4627
+ if (from === 3) return actionTileId.length > 0;
4628
+ return true;
4629
+ }
4630
+ const goNext = useCallback(() => {
4631
+ if (!canAdvance(step)) return;
4632
+ if (step < TOTAL_STEPS3) goToStep(step + 1);
4633
+ }, [step, name, actionTileId]);
4634
+ const goBack = useCallback(() => {
4635
+ if (step > 1) goToStep(step - 1);
4636
+ }, [step, goToStep]);
4637
+ const cancelWithConfirm = useCallback(() => {
4638
+ if (touched && !window.confirm(labels.wizardCancelConfirm)) return;
4639
+ onCancel();
4640
+ }, [touched, labels.wizardCancelConfirm, onCancel]);
4641
+ function combineDateTime(date, time) {
4642
+ if (!date) return null;
4643
+ const next = new Date(date);
4644
+ next.setHours(time?.hours ?? 0, time?.minutes ?? 0, 0, 0);
4645
+ return next.toISOString();
4646
+ }
4647
+ const tags = useMemo(
4648
+ () => tagsInput.split(",").map((t) => t.trim()).filter((t) => t.length > 0),
4649
+ [tagsInput]
4650
+ );
4651
+ function buildPayload() {
4652
+ const validFrom = combineDateTime(validFromDate, validFromTime);
4653
+ const validUntil = noExpiry ? null : combineDateTime(validUntilDate, validUntilTime);
4654
+ const conditionWithCombinator = combinator === "not" ? {
4655
+ operator: "boolean_expression",
4656
+ combinator: "and",
4657
+ operands: [condition],
4658
+ // The engine ignores extra fields, so this is forward-compat.
4659
+ ...{ notFlag: true }
4660
+ } : combinator === "or" ? {
4661
+ operator: "boolean_expression",
4662
+ combinator: "or",
4663
+ operands: [condition]
4664
+ } : condition;
4665
+ const finalAction = {
4666
+ type: action.type,
4667
+ params: {
4668
+ ...action.params ?? {},
4669
+ actionVariant: actionTileId,
4670
+ recurrence,
4671
+ ...recurrence === "cron" && cronExpression ? { cronExpression } : {},
4672
+ ...recurrence === "recurring" ? {
4673
+ weekdays,
4674
+ ...recurringTime ? { timeOfDay: `${pad(recurringTime.hours)}:${pad(recurringTime.minutes)}` } : {}
4675
+ } : {}
4676
+ }
4677
+ };
4678
+ const wireStatus = status === "paused" ? "draft" : status;
4679
+ return {
4680
+ name: name.trim() || "Untitled Rule",
4681
+ description: description.trim() || void 0,
4682
+ enabled,
4683
+ priority,
4684
+ status: wireStatus,
4685
+ validFrom,
4686
+ validUntil,
4687
+ tags,
4688
+ condition: conditionWithCombinator,
4689
+ action: finalAction
4690
+ };
4691
+ }
4692
+ async function submit() {
4693
+ setSubmitting(true);
4694
+ try {
4695
+ await onSubmit(buildPayload());
4696
+ } finally {
4697
+ setSubmitting(false);
4698
+ }
4699
+ }
4700
+ useEffect(() => {
4701
+ function onKey(e) {
4702
+ if (e.key === "Escape") {
4703
+ e.preventDefault();
4704
+ cancelWithConfirm();
4705
+ return;
4706
+ }
4707
+ if (e.key === "Enter") {
4708
+ const target = e.target;
4709
+ const tag = target?.tagName?.toLowerCase();
4710
+ if (tag === "textarea" || tag === "select" || tag === "input" || tag === "button") return;
4711
+ e.preventDefault();
4712
+ if (step < TOTAL_STEPS3) goNext();
4713
+ else void submit();
4714
+ }
4715
+ }
4716
+ window.addEventListener("keydown", onKey);
4717
+ return () => window.removeEventListener("keydown", onKey);
4718
+ }, [step, name, actionTileId, touched]);
4719
+ const stepTitles = [
4720
+ labels.wizardStep1Title,
4721
+ labels.wizardStep2Title,
4722
+ labels.wizardStep3Title,
4723
+ labels.wizardStep4Title,
4724
+ labels.wizardStep5Title
4725
+ ];
4726
+ const stepSubtitles = [
4727
+ labels.wizardStep1Subtitle,
4728
+ labels.wizardStep2Subtitle,
4729
+ labels.wizardStep3Subtitle,
4730
+ labels.wizardStep4Subtitle,
4731
+ labels.wizardStep5Subtitle
4732
+ ];
4733
+ const timelineSteps = stepTitles.map((title, idx) => ({
4734
+ id: String(idx + 1),
4735
+ name: title,
4736
+ description: stepSubtitles[idx],
4737
+ status: idx + 1 < step ? "complete" : idx + 1 === step ? "current" : "upcoming"
4738
+ }));
4739
+ const counter = labels.wizardStepCounter.replace("{current}", String(step)).replace("{total}", String(TOTAL_STEPS3));
4740
+ const hero = /* @__PURE__ */ jsx(
4741
+ HeroSection,
4742
+ {
4743
+ icon: /* @__PURE__ */ jsx(AdjustmentsHorizontalIcon, { className: "h-5 w-5" }),
4744
+ label: counter,
4745
+ title: labels.pageTitle,
4746
+ subtitle: stepSubtitles[step - 1] ?? labels.pageSubtitle,
4747
+ gradient: "from-fuchsia-500 to-purple-700"
4748
+ }
4749
+ );
4750
+ function renderStep1() {
4751
+ return /* @__PURE__ */ jsx(
4752
+ SectionCard,
4753
+ {
4754
+ variant: "glass",
4755
+ header: {
4756
+ title: labels.wizardStep1Title,
4757
+ subtitle: labels.wizardStep1Subtitle
4758
+ },
4759
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4760
+ /* @__PURE__ */ jsx(
4761
+ FormInput,
4762
+ {
4763
+ label: labels.nameLabel,
4764
+ value: name,
4765
+ onValueChange: (v) => {
4766
+ setName(v);
4767
+ markTouched();
4768
+ },
4769
+ placeholder: labels.namePlaceholder,
4770
+ required: true
4771
+ }
4772
+ ),
4773
+ /* @__PURE__ */ jsx(
4774
+ FormTextarea,
4775
+ {
4776
+ label: labels.descriptionLabel,
4777
+ value: description,
4778
+ onValueChange: (v) => {
4779
+ setDescription(v);
4780
+ markTouched();
4781
+ },
4782
+ placeholder: labels.descriptionPlaceholder,
4783
+ rows: 3
4784
+ }
4785
+ ),
4786
+ /* @__PURE__ */ jsx(
4787
+ RangeSliderField2,
4788
+ {
4789
+ sliderId: "wizard-rule-priority",
4790
+ label: labels.priorityLabel,
4791
+ value: priority,
4792
+ onChange: (v) => {
4793
+ setPriority(Math.round(v));
4794
+ markTouched();
4795
+ },
4796
+ min: 0,
4797
+ max: 100,
4798
+ step: 1,
4799
+ trackGradient: "linear-gradient(90deg, #10b981, #38bdf8 33%, #f59e0b 66%, #f43f5e)",
4800
+ formatValue: (v) => String(Math.round(v)),
4801
+ zones: [
4802
+ { label: labels.priorityLow, max: 25, color: "text-emerald-500", thumbColor: "#10b981" },
4803
+ { label: labels.priorityNormal, max: 50, color: "text-sky-500", thumbColor: "#38bdf8" },
4804
+ { label: labels.priorityHigh, max: 75, color: "text-amber-500", thumbColor: "#f59e0b" },
4805
+ { label: labels.priorityCritical, max: 100, color: "text-rose-500", thumbColor: "#f43f5e" }
4806
+ ]
4807
+ }
4808
+ ),
4809
+ /* @__PURE__ */ jsx(
4810
+ FormToggle,
4811
+ {
4812
+ checked: enabled,
4813
+ onChange: (v) => {
4814
+ setEnabled(v);
4815
+ markTouched();
4816
+ },
4817
+ label: labels.enabledLabel,
4818
+ variant: "card"
4819
+ }
4820
+ )
4821
+ ] })
4822
+ }
4823
+ );
4824
+ }
4825
+ function renderStep2() {
4826
+ return /* @__PURE__ */ jsx(
4827
+ SectionCard,
4828
+ {
4829
+ variant: "glass",
4830
+ header: {
4831
+ title: labels.conditionSectionTitle,
4832
+ subtitle: labels.conditionSectionSubtitle
4833
+ },
4834
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
4835
+ /* @__PURE__ */ jsxs("div", { children: [
4836
+ /* @__PURE__ */ jsx("span", { className: "mb-2 block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.combinatorLabel }),
4837
+ /* @__PURE__ */ jsx(
4838
+ SegmentedControl,
4839
+ {
4840
+ segments: [
4841
+ { value: "and", label: labels.combinatorAnd },
4842
+ { value: "or", label: labels.combinatorOr },
4843
+ { value: "not", label: labels.combinatorNot }
4844
+ ],
4845
+ value: combinator,
4846
+ onChange: (v) => {
4847
+ setCombinator(v);
4848
+ markTouched();
4849
+ },
4850
+ size: "sm"
4851
+ }
4852
+ )
4853
+ ] }),
4854
+ /* @__PURE__ */ jsx(
4855
+ RuleConditionBuilder,
4856
+ {
4857
+ value: condition,
4858
+ onChange: (next) => {
4859
+ setCondition(next);
4860
+ markTouched();
4861
+ }
4862
+ }
4863
+ )
4864
+ ] })
4865
+ }
4866
+ );
4867
+ }
4868
+ function renderStep3() {
4869
+ const selectedTile = ACTION_TILES.find((t) => t.id === actionTileId) ?? null;
4870
+ return /* @__PURE__ */ jsx(
4871
+ SectionCard,
4872
+ {
4873
+ variant: "glass",
4874
+ header: {
4875
+ title: labels.actionSectionTitle,
4876
+ subtitle: labels.actionSectionSubtitle
4877
+ },
4878
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
4879
+ /* @__PURE__ */ jsx(
4880
+ "div",
4881
+ {
4882
+ role: "radiogroup",
4883
+ "aria-label": labels.actionSectionTitle,
4884
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",
4885
+ children: ACTION_TILES.map((tile) => {
4886
+ const Icon = tile.icon;
4887
+ const selected = tile.id === actionTileId;
4888
+ const label = labels[tile.labelKey] ?? tile.id;
4889
+ const description2 = labels[tile.descriptionKey] ?? "";
4890
+ return /* @__PURE__ */ jsx(
4891
+ FilterTileButton,
4892
+ {
4893
+ isActive: selected,
4894
+ color: tile.color,
4895
+ icon: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" }),
4896
+ label,
4897
+ count: description2,
4898
+ onClick: () => {
4899
+ setActionTileId(tile.id);
4900
+ markTouched();
4901
+ }
4902
+ },
4903
+ tile.id
4904
+ );
4905
+ })
4906
+ }
4907
+ ),
4908
+ selectedTile && /* @__PURE__ */ jsx(
4909
+ SectionCard,
4910
+ {
4911
+ variant: "glass",
4912
+ header: {
4913
+ title: labels[selectedTile.labelKey] ?? selectedTile.id,
4914
+ subtitle: labels.actionConfigSubtitle
4915
+ },
4916
+ children: /* @__PURE__ */ jsx(
4917
+ RuleActionBuilder,
4918
+ {
4919
+ value: action,
4920
+ onChange: (next) => {
4921
+ setAction(next);
4922
+ markTouched();
4923
+ }
4924
+ }
4925
+ )
4926
+ }
4927
+ )
4928
+ ] })
4929
+ }
4930
+ );
4931
+ }
4932
+ function renderStep4() {
4933
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsx(
4934
+ SectionCard,
4935
+ {
4936
+ variant: "glass",
4937
+ header: {
4938
+ title: labels.scheduleSectionTitle,
4939
+ subtitle: labels.scheduleSectionSubtitle
4940
+ },
4941
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
4942
+ /* @__PURE__ */ jsxs(FormGrid, { children: [
4943
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
4944
+ /* @__PURE__ */ jsx("span", { className: "block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.validFromLabel }),
4945
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4946
+ /* @__PURE__ */ jsx(
4947
+ DatePicker,
4948
+ {
4949
+ value: validFromDate,
4950
+ onChange: (d) => {
4951
+ setValidFromDate(d);
4952
+ markTouched();
4953
+ },
4954
+ placeholder: labels.validFromDateLabel
4955
+ }
4956
+ ),
4957
+ /* @__PURE__ */ jsx(
4958
+ TimePicker,
4959
+ {
4960
+ value: validFromTime,
4961
+ onChange: (t) => {
4962
+ setValidFromTime(t);
4963
+ markTouched();
4964
+ },
4965
+ placeholder: labels.validFromTimeLabel
4966
+ }
4967
+ )
4968
+ ] })
4969
+ ] }),
4970
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
4971
+ /* @__PURE__ */ jsx("span", { className: "block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.validUntilLabel }),
4972
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4973
+ /* @__PURE__ */ jsx(
4974
+ DatePicker,
4975
+ {
4976
+ value: validUntilDate,
4977
+ onChange: (d) => {
4978
+ setValidUntilDate(d);
4979
+ markTouched();
4980
+ },
4981
+ placeholder: labels.validUntilDateLabel
4982
+ }
4983
+ ),
4984
+ /* @__PURE__ */ jsx(
4985
+ TimePicker,
4986
+ {
4987
+ value: validUntilTime,
4988
+ onChange: (t) => {
4989
+ setValidUntilTime(t);
4990
+ markTouched();
4991
+ },
4992
+ placeholder: labels.validUntilTimeLabel
4993
+ }
4994
+ )
4995
+ ] })
4996
+ ] })
4997
+ ] }),
4998
+ /* @__PURE__ */ jsx(
4999
+ FormCheckbox,
5000
+ {
5001
+ checked: noExpiry,
5002
+ onChange: (v) => {
5003
+ setNoExpiry(v);
5004
+ markTouched();
5005
+ },
5006
+ label: labels.noExpiryLabel,
5007
+ description: labels.noExpiryDescription
5008
+ }
5009
+ ),
5010
+ /* @__PURE__ */ jsxs("div", { children: [
5011
+ /* @__PURE__ */ jsx("span", { className: "mb-2 block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.statusLabel }),
5012
+ /* @__PURE__ */ jsx(
5013
+ SegmentedControl,
5014
+ {
5015
+ segments: [
5016
+ { value: "active", label: labels.statusActive },
5017
+ { value: "paused", label: labels.statusPaused },
5018
+ { value: "archived", label: labels.statusArchived }
5019
+ ],
5020
+ value: status,
5021
+ onChange: (v) => {
5022
+ setStatus(v);
5023
+ markTouched();
5024
+ },
5025
+ size: "sm"
5026
+ }
5027
+ )
5028
+ ] }),
5029
+ /* @__PURE__ */ jsx(
5030
+ FormInput,
5031
+ {
5032
+ label: labels.tagsLabel,
5033
+ value: tagsInput,
5034
+ onValueChange: (v) => {
5035
+ setTagsInput(v);
5036
+ markTouched();
5037
+ },
5038
+ placeholder: labels.tagsPlaceholder,
5039
+ hint: labels.tagsHint
5040
+ }
5041
+ ),
5042
+ /* @__PURE__ */ jsxs("div", { children: [
5043
+ /* @__PURE__ */ jsx("span", { className: "mb-2 block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.recurrenceLabel }),
5044
+ /* @__PURE__ */ jsx(
5045
+ SegmentedControl,
5046
+ {
5047
+ segments: [
5048
+ { value: "one-off", label: labels.recurrenceOneOff },
5049
+ { value: "cron", label: labels.recurrenceCron },
5050
+ { value: "recurring", label: labels.recurrenceRecurring }
5051
+ ],
5052
+ value: recurrence,
5053
+ onChange: (v) => {
5054
+ setRecurrence(v);
5055
+ markTouched();
5056
+ },
5057
+ size: "sm"
5058
+ }
5059
+ )
5060
+ ] }),
5061
+ recurrence === "cron" && /* @__PURE__ */ jsx(
5062
+ FormInput,
5063
+ {
5064
+ label: labels.cronExpressionLabel,
5065
+ value: cronExpression,
5066
+ onValueChange: (v) => {
5067
+ setCronExpression(v);
5068
+ markTouched();
5069
+ },
5070
+ placeholder: labels.cronExpressionPlaceholder,
5071
+ hint: labels.cronExpressionHint
5072
+ }
5073
+ ),
5074
+ recurrence === "recurring" && /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
5075
+ /* @__PURE__ */ jsxs("div", { children: [
5076
+ /* @__PURE__ */ jsx("span", { className: "mb-2 block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.weekdaysLabel }),
5077
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: WEEKDAYS.map((d) => {
5078
+ const selected = weekdays.includes(d.id);
5079
+ const label = labels[d.labelKey] ?? d.id;
5080
+ return /* @__PURE__ */ jsx(
5081
+ "button",
5082
+ {
5083
+ type: "button",
5084
+ "aria-pressed": selected,
5085
+ onClick: () => {
5086
+ setWeekdays(
5087
+ (current) => current.includes(d.id) ? current.filter((id) => id !== d.id) : [...current, d.id]
5088
+ );
5089
+ markTouched();
5090
+ },
5091
+ className: [
5092
+ "inline-flex h-9 min-w-9 items-center justify-center rounded-full px-3 text-xs font-semibold transition",
5093
+ selected ? "bg-fuchsia-500 text-white shadow ring-2 ring-fuchsia-300/70" : "liquid-surface text-slate-700 dark:text-slate-300 hover:bg-fuchsia-500/10"
5094
+ ].join(" "),
5095
+ children: label
5096
+ },
5097
+ d.id
5098
+ );
5099
+ }) })
5100
+ ] }),
5101
+ /* @__PURE__ */ jsxs("div", { children: [
5102
+ /* @__PURE__ */ jsx("span", { className: "mb-2 block text-xs font-semibold uppercase tracking-wider text-slate-600 dark:text-slate-400", children: labels.timeOfDayLabel }),
5103
+ /* @__PURE__ */ jsx(
5104
+ TimePicker,
5105
+ {
5106
+ value: recurringTime,
5107
+ onChange: (t) => {
5108
+ setRecurringTime(t);
5109
+ markTouched();
5110
+ },
5111
+ placeholder: labels.timeOfDayLabel
5112
+ }
5113
+ )
5114
+ ] })
5115
+ ] })
5116
+ ] })
5117
+ }
5118
+ ) });
5119
+ }
5120
+ function renderStep5() {
5121
+ const payload = buildPayload();
5122
+ const conditionSentence = humanReadableCondition(payload.condition, labels);
5123
+ const actionSentence = humanReadableAction(payload.action, labels, ACTION_TILES, actionTileId);
5124
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
5125
+ /* @__PURE__ */ jsx(
5126
+ SectionCard,
5127
+ {
5128
+ variant: "glass",
5129
+ header: {
5130
+ title: labels.wizardStep1Title,
5131
+ subtitle: labels.wizardStep1Subtitle
5132
+ },
5133
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(1), children: [
5134
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
5135
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
5136
+ ] }),
5137
+ children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
5138
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewNameLabel, value: payload.name }),
5139
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewPriorityLabel, value: String(payload.priority) }),
5140
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewEnabledLabel, value: payload.enabled ? labels.reviewYes : labels.reviewNo }),
5141
+ /* @__PURE__ */ jsx(
5142
+ ReviewRow3,
5143
+ {
5144
+ label: labels.reviewDescriptionLabel,
5145
+ value: payload.description ?? labels.reviewNoneValue
5146
+ }
5147
+ )
5148
+ ] })
5149
+ }
5150
+ ),
5151
+ /* @__PURE__ */ jsxs(
5152
+ SectionCard,
5153
+ {
5154
+ variant: "glass",
5155
+ header: {
5156
+ title: labels.wizardStep2Title,
5157
+ subtitle: labels.wizardStep2Subtitle
5158
+ },
5159
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(2), children: [
5160
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
5161
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
5162
+ ] }),
5163
+ children: [
5164
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-sm text-slate-700 dark:text-slate-200", children: conditionSentence }),
5165
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewCombinatorLabel, value: combinator.toUpperCase() }),
5166
+ /* @__PURE__ */ jsx("pre", { className: "mt-3 max-h-48 overflow-auto rounded-lg border border-slate-200/70 bg-slate-50/60 p-2 text-xs text-slate-700 dark:border-slate-700 dark:bg-slate-900/40 dark:text-slate-200", children: JSON.stringify(payload.condition, null, 2) })
5167
+ ]
5168
+ }
5169
+ ),
5170
+ /* @__PURE__ */ jsxs(
5171
+ SectionCard,
5172
+ {
5173
+ variant: "glass",
5174
+ header: {
5175
+ title: labels.wizardStep3Title,
5176
+ subtitle: labels.wizardStep3Subtitle
5177
+ },
5178
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(3), children: [
5179
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
5180
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
5181
+ ] }),
5182
+ children: [
5183
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-sm text-slate-700 dark:text-slate-200", children: actionSentence }),
5184
+ /* @__PURE__ */ jsx("pre", { className: "mt-3 max-h-48 overflow-auto rounded-lg border border-slate-200/70 bg-slate-50/60 p-2 text-xs text-slate-700 dark:border-slate-700 dark:bg-slate-900/40 dark:text-slate-200", children: JSON.stringify(payload.action, null, 2) })
5185
+ ]
5186
+ }
5187
+ ),
5188
+ /* @__PURE__ */ jsx(
5189
+ SectionCard,
5190
+ {
5191
+ variant: "glass",
5192
+ header: {
5193
+ title: labels.wizardStep4Title,
5194
+ subtitle: labels.wizardStep4Subtitle
5195
+ },
5196
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", outline: true, onClick: () => goToStep(4), children: [
5197
+ /* @__PURE__ */ jsx(PencilSquareIcon, { className: "h-4 w-4" }),
5198
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5", children: labels.wizardReviewEdit })
5199
+ ] }),
5200
+ children: /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
5201
+ /* @__PURE__ */ jsx(
5202
+ ReviewRow3,
5203
+ {
5204
+ label: labels.reviewValidFromLabel,
5205
+ value: payload.validFrom ?? labels.reviewNoneValue
5206
+ }
5207
+ ),
5208
+ /* @__PURE__ */ jsx(
5209
+ ReviewRow3,
5210
+ {
5211
+ label: labels.reviewValidUntilLabel,
5212
+ value: payload.validUntil ?? (noExpiry ? labels.noExpiryLabel : labels.reviewNoneValue)
5213
+ }
5214
+ ),
5215
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewStatusLabel, value: payload.status ?? "active" }),
5216
+ /* @__PURE__ */ jsx(
5217
+ ReviewRow3,
5218
+ {
5219
+ label: labels.reviewTagsLabel,
5220
+ value: payload.tags && payload.tags.length > 0 ? payload.tags.join(", ") : labels.reviewNoneValue
5221
+ }
5222
+ ),
5223
+ /* @__PURE__ */ jsx(ReviewRow3, { label: labels.reviewRecurrenceLabel, value: recurrence })
5224
+ ] })
5225
+ }
5226
+ )
5227
+ ] });
5228
+ }
5229
+ const stepBody = step === 1 ? renderStep1() : step === 2 ? renderStep2() : step === 3 ? renderStep3() : step === 4 ? renderStep4() : renderStep5();
5230
+ const advanceDisabled = !canAdvance(step);
5231
+ const footer = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-t border-slate-200/60 pt-4 dark:border-white/10", children: [
5232
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(Button, { type: "button", outline: true, onClick: goBack, disabled: step === 1 || submitting, children: labels.wizardBack }) }),
5233
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
5234
+ /* @__PURE__ */ jsx(Button, { type: "button", outline: true, onClick: cancelWithConfirm, disabled: submitting, children: labels.wizardCancel }),
5235
+ step < TOTAL_STEPS3 ? /* @__PURE__ */ jsx(Button, { type: "button", color: "fuchsia", onClick: goNext, disabled: advanceDisabled || submitting, children: labels.wizardNext }) : /* @__PURE__ */ jsx(
5236
+ Button,
5237
+ {
5238
+ type: "button",
5239
+ color: "fuchsia",
5240
+ onClick: () => void submit(),
5241
+ disabled: submitting || !name.trim() || !actionTileId,
5242
+ children: submitting ? labels.wizardCreate + "\u2026" : labels.wizardCreate
5243
+ }
5244
+ )
5245
+ ] })
5246
+ ] });
5247
+ const content = /* @__PURE__ */ jsxs(
5248
+ "form",
5249
+ {
5250
+ onSubmit: (e) => {
5251
+ e.preventDefault();
5252
+ if (step < TOTAL_STEPS3) goNext();
5253
+ else void submit();
5254
+ },
5255
+ className: "space-y-5",
5256
+ children: [
5257
+ /* @__PURE__ */ jsx(
5258
+ StepTimeline,
5259
+ {
5260
+ steps: timelineSteps,
5261
+ progressLabel: labels.pageTitle,
5262
+ onStepClick: (idx) => goToStep(idx + 1)
5263
+ }
5264
+ ),
5265
+ /* @__PURE__ */ jsxs("div", { className: "w-full space-y-5", children: [
5266
+ stepBody,
5267
+ footer
5268
+ ] })
5269
+ ]
5270
+ }
5271
+ );
5272
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
5273
+ hero,
5274
+ content
5275
+ ] });
5276
+ }
5277
+ function ReviewRow3({ label, value }) {
5278
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-slate-200/60 bg-white/40 px-3 py-2 dark:border-white/10 dark:bg-white/[0.04]", children: [
5279
+ /* @__PURE__ */ jsx("dt", { className: "text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500", children: label }),
5280
+ /* @__PURE__ */ jsx("dd", { className: "mt-0.5 whitespace-pre-wrap break-words text-xs font-semibold text-gray-900 dark:text-white", children: value })
5281
+ ] });
5282
+ }
5283
+ function pad(n) {
5284
+ return String(n).padStart(2, "0");
5285
+ }
5286
+ function humanReadableCondition(cond, labels) {
5287
+ if (!cond) return labels.reviewNoneValue;
5288
+ if (cond.operator === "boolean_expression" && Array.isArray(cond.operands)) {
5289
+ const inner = cond.operands.map((o) => humanReadableCondition(o, labels)).join(` ${cond.combinator?.toUpperCase() ?? "AND"} `);
5290
+ return `(${inner})`;
5291
+ }
5292
+ const field = cond.field ?? "?";
5293
+ switch (cond.operator) {
5294
+ case "truthy":
5295
+ return `${field} is set`;
5296
+ case "eq":
5297
+ return `${field} = ${formatValue(cond.value)}`;
5298
+ case "neq":
5299
+ return `${field} \u2260 ${formatValue(cond.value)}`;
5300
+ case "gt":
5301
+ return `${field} > ${formatValue(cond.value)}`;
5302
+ case "gte":
5303
+ return `${field} \u2265 ${formatValue(cond.value)}`;
5304
+ case "lt":
5305
+ return `${field} < ${formatValue(cond.value)}`;
5306
+ case "lte":
5307
+ return `${field} \u2264 ${formatValue(cond.value)}`;
5308
+ case "contains":
5309
+ return `${field} contains "${formatValue(cond.value)}"`;
5310
+ case "regex_match":
5311
+ return `${field} matches /${cond.pattern ?? ""}/`;
5312
+ case "threshold":
5313
+ return `${field} ${cond.comparison ?? "gte"} ${formatValue(cond.value)}`;
5314
+ case "time_window":
5315
+ return `${field} within time-window(${(cond.windows ?? []).length})`;
5316
+ default:
5317
+ return `${cond.operator}(${field})`;
5318
+ }
5319
+ }
5320
+ function formatValue(v) {
5321
+ if (v === null || v === void 0) return "";
5322
+ return String(v);
5323
+ }
5324
+ function humanReadableAction(action, labels, tiles, actionTileId) {
5325
+ const tile = tiles.find((t) => t.id === actionTileId);
5326
+ const tileLabel = tile ? labels[tile.labelKey] ?? tile.id : action.type;
5327
+ const paramSummary = action.params ? Object.entries(action.params).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`).join(", ") : "";
5328
+ return paramSummary ? `${tileLabel} \u2014 ${paramSummary}` : tileLabel;
5329
+ }
3619
5330
 
3620
- export { AgentNewWizardPageView, AgentsConfigPageView, AgentsIndexPageView, AgentsModelsPageView, AgentsPromptsPageView, AgentsToolDefinitionsPageView, AgentsWorkspacePageView, ConnectionsPageView, CredentialsPageView, DashboardPageView, DatasourcesPageView, RulesPageView, RunTimelinePageView, TOOL_TYPES, WorkflowRunsPageView, WorkflowsPageView, jsonSchemaToParameters, parametersToJsonSchema };
5331
+ export { AgentNewWizardPageView, AgentsConfigPageView, AgentsIndexPageView, AgentsModelsPageView, AgentsPromptsPageView, AgentsToolDefinitionsPageView, AgentsWorkspacePageView, ConnectionsPageView, CredentialsPageView, DashboardPageView, DatasourceNewWizardPageView, DatasourcesPageView, RuleNewWizardPageView, RulesPageView, RunTimelinePageView, TOOL_TYPES, WorkflowRunsPageView, WorkflowsPageView, jsonSchemaToParameters, parametersToJsonSchema };
3621
5332
  //# sourceMappingURL=index.mjs.map
3622
5333
  //# sourceMappingURL=index.mjs.map