From dfb04a6360256860e9c4a9193cf1b56b35e20658 Mon Sep 17 00:00:00 2001 From: LoggeL Date: Tue, 6 Jan 2026 21:19:05 +0000 Subject: [PATCH 1/3] feat: add select menu component entry for flow editor Add entry_component_select node type similar to entry_component_button, allowing users to create flows triggered by Discord select menu interactions. Frontend changes: - Add FlowNodeEntryComponentSelect component - Register entry_component_select in node types and components - Add nodeEntryComponentSelectDataSchema - Add component_select to FlowContextType - Include component_select in Responses action context Backend changes: - Add FlowNodeTypeEntryComponentSelect constant - Add CompileComponentSelect function - Add IsComponentSelectEntry helper - Update IsEntry to include select component - Update execute.go to handle select entry - Update message.go to handle StringSelectInteraction --- kite-service/internal/core/engine/message.go | 35 ++-- kite-service/pkg/flow/compile.go | 9 + kite-service/pkg/flow/data.go | 1 + kite-service/pkg/flow/execute.go | 2 +- kite-web/package-lock.json | 177 +++++------------- .../flow/FlowNodeEntryComponentSelect.tsx | 12 ++ .../src/components/flow/FlowNodeExplorer.tsx | 2 +- kite-web/src/lib/flow/components.ts | 2 + kite-web/src/lib/flow/context.tsx | 2 +- kite-web/src/lib/flow/dataSchema.ts | 2 + kite-web/src/lib/flow/nodes.ts | 11 ++ 11 files changed, 105 insertions(+), 150 deletions(-) create mode 100644 kite-web/src/components/flow/FlowNodeEntryComponentSelect.tsx diff --git a/kite-service/internal/core/engine/message.go b/kite-service/internal/core/engine/message.go index cd5ed85c..ed7dfc8a 100644 --- a/kite-service/internal/core/engine/message.go +++ b/kite-service/internal/core/engine/message.go @@ -27,18 +27,23 @@ func NewMessageInstance( flows := make(map[string]*flow.CompiledFlowNode, len(msg.FlowSources)) for id, flowSource := range msg.FlowSources { - flow, err := flow.CompileComponentButton(flowSource) + // Try to compile as button first, then as select menu + compiledFlow, err := flow.CompileComponentButton(flowSource) if err != nil { - slog.Error( - "Failed to compile component button flow", - slog.String("app_id", appID), - slog.String("message_id", msg.MessageID), - slog.String("error", err.Error()), - ) - continue + // Try compiling as select menu + compiledFlow, err = flow.CompileComponentSelect(flowSource) + if err != nil { + slog.Error( + "Failed to compile component flow", + slog.String("app_id", appID), + slog.String("message_id", msg.MessageID), + slog.String("error", err.Error()), + ) + continue + } } - flows[id] = flow + flows[id] = compiledFlow } return &MessageInstance{ @@ -55,13 +60,17 @@ func (m *MessageInstance) HandleEvent(appID string, session *state.State, event return } - d, ok := i.InteractionEvent.Data.(*discord.ButtonInteraction) - if !ok { + var flowSourceID string + + switch d := i.InteractionEvent.Data.(type) { + case *discord.ButtonInteraction: + flowSourceID = string(d.CustomID) + case *discord.StringSelectInteraction: + flowSourceID = string(d.CustomID) + default: return } - flowSourceID := string(d.CustomID) - links := entityLinks{ MessageID: null.NewString(m.msg.MessageID, true), MessageInstanceID: null.NewInt(int64(m.msg.ID), true), diff --git a/kite-service/pkg/flow/compile.go b/kite-service/pkg/flow/compile.go index 7db28c05..aa8400cd 100644 --- a/kite-service/pkg/flow/compile.go +++ b/kite-service/pkg/flow/compile.go @@ -20,6 +20,10 @@ func CompileComponentButton(data FlowData) (*CompiledFlowNode, error) { return compile(data, FlowNodeTypeEntryComponentButton) } +func CompileComponentSelect(data FlowData) (*CompiledFlowNode, error) { + return compile(data, FlowNodeTypeEntryComponentSelect) +} + func CompileEventListener(data FlowData) (*CompiledFlowNode, error) { return compile(data, FlowNodeTypeEntryEvent) } @@ -105,6 +109,7 @@ type ConnectedFlowNodes struct { func (n *CompiledFlowNode) IsEntry() bool { return n.Type == FlowNodeTypeEntryCommand || n.Type == FlowNodeTypeEntryComponentButton || + n.Type == FlowNodeTypeEntryComponentSelect || n.Type == FlowNodeTypeEntryEvent } @@ -112,6 +117,10 @@ func (n *CompiledFlowNode) IsComponentButtonEntry() bool { return n.Type == FlowNodeTypeEntryComponentButton } +func (n *CompiledFlowNode) IsComponentSelectEntry() bool { + return n.Type == FlowNodeTypeEntryComponentSelect +} + func (n *CompiledFlowNode) IsEventListenerEntry() bool { return n.Type == FlowNodeTypeEntryEvent } diff --git a/kite-service/pkg/flow/data.go b/kite-service/pkg/flow/data.go index 5a592b7d..2422333a 100644 --- a/kite-service/pkg/flow/data.go +++ b/kite-service/pkg/flow/data.go @@ -43,6 +43,7 @@ const ( FlowNodeTypeEntryCommand FlowNodeType = "entry_command" FlowNodeTypeEntryEvent FlowNodeType = "entry_event" FlowNodeTypeEntryComponentButton FlowNodeType = "entry_component_button" + FlowNodeTypeEntryComponentSelect FlowNodeType = "entry_component_select" FlowNodeTypeOptionCommandArgument FlowNodeType = "option_command_argument" FlowNodeTypeOptionCommandPermissions FlowNodeType = "option_command_permissions" diff --git a/kite-service/pkg/flow/execute.go b/kite-service/pkg/flow/execute.go index 034d40ec..9ed7bdc3 100644 --- a/kite-service/pkg/flow/execute.go +++ b/kite-service/pkg/flow/execute.go @@ -36,7 +36,7 @@ func (n *CompiledFlowNode) Execute(ctx *FlowContext) error { defer ctx.endOperation() switch n.Type { - case FlowNodeTypeEntryCommand, FlowNodeTypeEntryComponentButton: + case FlowNodeTypeEntryCommand, FlowNodeTypeEntryComponentButton, FlowNodeTypeEntryComponentSelect: if !ctx.IsEntry() { return fmt.Errorf("command entry isn't the entry node") } diff --git a/kite-web/package-lock.json b/kite-web/package-lock.json index c0443e8b..7fc413bc 100644 --- a/kite-web/package-lock.json +++ b/kite-web/package-lock.json @@ -99,7 +99,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "engines": { "node": ">=10" }, @@ -208,6 +207,7 @@ "version": "6.33.0", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz", "integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==", + "peer": true, "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -388,7 +388,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -405,7 +404,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -417,7 +415,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -432,7 +429,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -446,7 +442,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -455,7 +450,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -463,14 +457,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -708,7 +700,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -721,7 +712,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -730,7 +720,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -743,7 +732,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true, "engines": { "node": ">=14" @@ -3617,6 +3605,7 @@ "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3626,7 +3615,8 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, + "devOptional": true, + "peer": true, "dependencies": { "@types/react": "*" } @@ -3948,6 +3938,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3984,7 +3975,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3993,7 +3983,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4007,14 +3996,12 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4026,8 +4013,7 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, "node_modules/argparse": { "version": "2.0.1", @@ -4270,8 +4256,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base16": { "version": "1.0.0", @@ -4282,7 +4267,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -4304,7 +4288,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4355,7 +4338,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "engines": { "node": ">= 6" } @@ -4444,7 +4426,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4468,7 +4449,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4859,7 +4839,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4870,8 +4849,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/comma-separated-tokens": { "version": "2.0.3", @@ -4886,7 +4864,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "engines": { "node": ">= 6" } @@ -4914,7 +4891,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4928,7 +4904,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -5034,6 +5009,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "peer": true, "engines": { "node": ">=12" } @@ -5173,6 +5149,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -5311,8 +5288,7 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/dir-glob": { "version": "3.0.1", @@ -5329,8 +5305,7 @@ "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/doctrine": { "version": "3.0.0", @@ -5356,19 +5331,18 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/emoji-mart": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", - "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==" + "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", + "peer": true }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/enhanced-resolve": { "version": "5.17.1", @@ -5578,6 +5552,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -5730,6 +5705,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, + "peer": true, "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -6022,7 +5998,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6038,7 +6013,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6062,7 +6036,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -6110,7 +6083,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6167,7 +6139,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6210,7 +6181,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -6224,7 +6194,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6316,7 +6285,6 @@ "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", @@ -6338,7 +6306,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -6350,7 +6317,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -6359,7 +6325,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6517,7 +6482,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -6602,6 +6566,7 @@ "version": "10.1.1", "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -6770,7 +6735,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6810,7 +6774,6 @@ "version": "2.15.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", - "dev": true, "dependencies": { "hasown": "^2.0.2" }, @@ -6864,7 +6827,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6885,7 +6847,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -6909,7 +6870,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -6954,7 +6914,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -7131,8 +7090,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/iterator.prototype": { "version": "1.1.2", @@ -7151,7 +7109,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -7169,7 +7126,6 @@ "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, "bin": { "jiti": "bin/jiti.js" } @@ -7296,7 +7252,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } @@ -7304,8 +7259,7 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/lit": { "version": "3.2.0", @@ -7411,8 +7365,7 @@ "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/lucide-react": { "version": "0.436.0", @@ -7572,7 +7525,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -8002,7 +7954,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -8036,7 +7987,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -8050,7 +8000,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -8085,6 +8034,7 @@ "resolved": "https://registry.npmjs.org/next/-/next-14.2.25.tgz", "integrity": "sha512-N5M7xMc4wSb4IkPvEV5X2BRRXUmhVHNyaXwEM86+voXthSZz8ZiRyQW4p9mwAoAPIm6OzuVZtn7idgEJeAJN3Q==", "license": "MIT", + "peer": true, "dependencies": { "@next/env": "14.2.25", "@swc/helpers": "0.5.5", @@ -8189,7 +8139,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8206,7 +8155,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "engines": { "node": ">= 6" } @@ -8443,7 +8391,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -8451,14 +8398,12 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -8488,7 +8433,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -8500,7 +8444,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8509,7 +8452,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "engines": { "node": ">= 6" } @@ -8527,7 +8469,6 @@ "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8542,6 +8483,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -8555,7 +8497,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -8572,7 +8513,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -8591,7 +8531,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8626,7 +8565,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, "engines": { "node": ">=14" }, @@ -8638,7 +8576,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8663,7 +8600,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8688,8 +8624,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -8745,7 +8680,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -8765,6 +8699,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -8809,6 +8744,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -8821,6 +8757,7 @@ "version": "7.52.2", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.2.tgz", "integrity": "sha512-pqfPEbERnxxiNMPd0bzmt1tuaPcVccywFDpyk2uV5xCIBphHV5T8SVnX9/o3kplPE1zzKt77+YIoq+EMwJp56A==", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -9027,7 +8964,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -9036,7 +8972,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -9160,7 +9095,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9195,7 +9129,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -9242,7 +9175,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -9362,7 +9294,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9374,7 +9305,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -9401,7 +9331,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -9476,7 +9405,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -9494,7 +9422,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9507,14 +9434,12 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -9526,7 +9451,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -9649,7 +9573,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -9662,7 +9585,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -9730,7 +9652,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -9764,7 +9685,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -9794,7 +9714,7 @@ "version": "3.4.10", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", - "dev": true, + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -9839,7 +9759,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9867,7 +9786,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -9876,7 +9794,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -9893,7 +9810,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -9939,8 +9855,7 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tsconfig-paths": { "version": "3.15.0", @@ -10077,6 +9992,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10333,8 +10249,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/vaul": { "version": "0.9.9", @@ -10420,7 +10335,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10523,7 +10437,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -10541,7 +10454,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -10557,14 +10469,12 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10578,7 +10488,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -10590,7 +10499,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -10602,7 +10510,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -10623,7 +10530,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", - "dev": true, "bin": { "yaml": "bin.mjs" }, @@ -10644,9 +10550,11 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -10681,6 +10589,7 @@ "version": "4.5.5", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", + "peer": true, "dependencies": { "use-sync-external-store": "1.2.2" }, diff --git a/kite-web/src/components/flow/FlowNodeEntryComponentSelect.tsx b/kite-web/src/components/flow/FlowNodeEntryComponentSelect.tsx new file mode 100644 index 00000000..226356a3 --- /dev/null +++ b/kite-web/src/components/flow/FlowNodeEntryComponentSelect.tsx @@ -0,0 +1,12 @@ +import { Position } from "@xyflow/react"; +import { NodeProps } from "@/lib/flow/dataSchema"; +import FlowNodeBase from "./FlowNodeBase"; +import FlowNodeHandle from "./FlowNodeHandle"; + +export default function FlowNodeEntryComponentSelect(props: NodeProps) { + return ( + + + + ); +} diff --git a/kite-web/src/components/flow/FlowNodeExplorer.tsx b/kite-web/src/components/flow/FlowNodeExplorer.tsx index a8d60936..08e16b33 100644 --- a/kite-web/src/components/flow/FlowNodeExplorer.tsx +++ b/kite-web/src/components/flow/FlowNodeExplorer.tsx @@ -38,7 +38,7 @@ const nodeCategories = { "action_response_defer", "suspend_response_modal", ], - contextTypes: ["command", "component_button"], + contextTypes: ["command", "component_button", "component_select"], }, { title: "Messages", diff --git a/kite-web/src/lib/flow/components.ts b/kite-web/src/lib/flow/components.ts index 5974505b..163b61ec 100644 --- a/kite-web/src/lib/flow/components.ts +++ b/kite-web/src/lib/flow/components.ts @@ -16,6 +16,7 @@ import FlowNodeConditionChannel from "@/components/flow/FlowNodeConditionChannel import FlowNodeConditionRole from "@/components/flow/FlowNodeConditionRole"; import FlowNodeControlSleep from "@/components/flow/FlowNodeControlSleep"; import FlowNodeEntryComponentButton from "@/components/flow/FlowNodeEntryComponentButton"; +import FlowNodeEntryComponentSelect from "@/components/flow/FlowNodeEntryComponentSelect"; import FlowNodeSuspendBase from "@/components/flow/FlowNodeSuspendBase"; import FlowNodeActionMessage from "@/components/flow/FlowNodeActionMessage"; import FlowNodeBase from "@/components/flow/FlowNodeBase"; @@ -25,6 +26,7 @@ export const nodeTypes = { entry_command: FlowNodeEntryCommand, entry_event: FlowNodeEntryEvent, entry_component_button: FlowNodeEntryComponentButton, + entry_component_select: FlowNodeEntryComponentSelect, option_command_argument: FlowNodeOptionCommandArgument, option_command_permissions: FlowNodeOptionBase, diff --git a/kite-web/src/lib/flow/context.tsx b/kite-web/src/lib/flow/context.tsx index a6330e16..d2849d32 100644 --- a/kite-web/src/lib/flow/context.tsx +++ b/kite-web/src/lib/flow/context.tsx @@ -9,7 +9,7 @@ import { import { create, useStore } from "zustand"; import { immer } from "zustand/middleware/immer"; -export type FlowContextType = "command" | "component_button" | "event_discord"; +export type FlowContextType = "command" | "component_button" | "component_select" | "event_discord"; export interface FlowContextStore { type: FlowContextType; diff --git a/kite-web/src/lib/flow/dataSchema.ts b/kite-web/src/lib/flow/dataSchema.ts index 50858680..2acc8448 100644 --- a/kite-web/src/lib/flow/dataSchema.ts +++ b/kite-web/src/lib/flow/dataSchema.ts @@ -119,6 +119,8 @@ export const nodeEntryEventDataSchema = nodeBaseDataSchema.extend({ export const nodeEntryComponentButtonDataSchema = nodeBaseDataSchema.extend({}); +export const nodeEntryComponentSelectDataSchema = nodeBaseDataSchema.extend({}); + export const nodeMessageDataSchema = z.object({ content: z.string().max(2000), allowed_mentions: z diff --git a/kite-web/src/lib/flow/nodes.ts b/kite-web/src/lib/flow/nodes.ts index 803d611b..2eb3cadf 100644 --- a/kite-web/src/lib/flow/nodes.ts +++ b/kite-web/src/lib/flow/nodes.ts @@ -51,6 +51,7 @@ import { NodeData, nodeEntryCommandDataSchema, nodeEntryComponentButtonDataSchema, + nodeEntryComponentSelectDataSchema, nodeEntryEventDataSchema, nodeOptionCommandArgumentDataSchema, nodeOptionCommandContextsSchema, @@ -129,6 +130,16 @@ export const nodeTypes: Record = { dataFields: [], fixed: true, }, + entry_component_select: { + color: entryColor, + icon: "list", + defaultTitle: "Select Menu", + defaultDescription: + "This gets triggered when a user selects an option. Drop different actions here!", + dataSchema: nodeEntryComponentSelectDataSchema, + dataFields: [], + fixed: true, + }, action_response_create: { color: actionColor, icon: "message-circle-reply", From acd8e7b211e87585b64a99dc66ec67c32b7e98e0 Mon Sep 17 00:00:00 2001 From: LoggeL Date: Tue, 6 Jan 2026 21:26:44 +0000 Subject: [PATCH 2/3] feat: add select menu handling in app.go and expose selected values - Handle StringSelectInteraction in app.go event handler - Add Values field to InteractionEnv for select menu selections - Expose 'values' at top level in eval context - Add value(index) helper function to access selected values --- kite-service/internal/core/engine/app.go | 23 +++++++++++++++++++++++ kite-service/pkg/eval/ctx.go | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/kite-service/internal/core/engine/app.go b/kite-service/internal/core/engine/app.go index 1313bb0b..744b4344 100644 --- a/kite-service/internal/core/engine/app.go +++ b/kite-service/internal/core/engine/app.go @@ -287,6 +287,29 @@ func (a *App) HandleEvent(appID string, session *state.State, event gateway.Even return } + go instance.HandleEvent(appID, session, event) + case *discord.StringSelectInteraction: + messageID := e.Message.ID.String() + messageInstnace, err := a.env.MessageInstanceStore.MessageInstanceByDiscordMessageID(context.TODO(), messageID) + if err != nil { + if errors.Is(err, store.ErrNotFound) { + return + } + + slog.With("error", err).Error("failed to get message instance by discord message ID") + return + } + + instance, err := NewMessageInstance( + a.id, + messageInstnace, + a.env, + ) + if err != nil { + slog.With("error", err).Error("failed to create message instance") + return + } + go instance.HandleEvent(appID, session, event) case *discord.ModalInteraction: customID := string(d.CustomID) diff --git a/kite-service/pkg/eval/ctx.go b/kite-service/pkg/eval/ctx.go index d0bb011d..077e1db8 100644 --- a/kite-service/pkg/eval/ctx.go +++ b/kite-service/pkg/eval/ctx.go @@ -30,6 +30,7 @@ type InteractionEnv struct { Member any `expr:"member" json:"member"` Command *CommandEnv `expr:"command" json:"command"` Components map[string]*ComponentEnv `expr:"components" json:"components"` + Values []string `expr:"values" json:"values"` } func NewInteractionEnv(i *discord.InteractionEvent) *InteractionEnv { @@ -39,6 +40,7 @@ func NewInteractionEnv(i *discord.InteractionEvent) *InteractionEnv { ID: i.ID.String(), Channel: NewSnowflakeEnv(i.ChannelID), Components: NewComponentsEnv(i), + Values: []string{}, } if i.Member != nil { @@ -57,6 +59,11 @@ func NewInteractionEnv(i *discord.InteractionEvent) *InteractionEnv { e.Command = NewCommandEnv(i) } + // Extract selected values from select menu interactions + if selectData, ok := i.Data.(*discord.StringSelectInteraction); ok { + e.Values = selectData.Values + } + return e } @@ -72,6 +79,7 @@ func NewContextFromInteraction(i *discord.InteractionEvent, session *state.State "user": interactionEnv.User, "member": interactionEnv.Member, "app": NewAppEnv(session), + "values": interactionEnv.Values, "arg": func(name string) any { if interactionEnv.Command == nil { @@ -90,6 +98,12 @@ func NewContextFromInteraction(i *discord.InteractionEvent, session *state.State } return nil }, + "value": func(index int) any { + if index < 0 || index >= len(interactionEnv.Values) { + return nil + } + return interactionEnv.Values[index] + }, }, } } From a6ec3766c166401f72df01577d404938db256cab Mon Sep 17 00:00:00 2001 From: LoggeL Date: Wed, 7 Jan 2026 06:07:41 +0000 Subject: [PATCH 3/3] feat: add select menu UI editor and backend conversion - Add MessageComponentSelectMenu.tsx component with full editor UI - Enable 'Add Select Menu Row' button in MessageComponentsSection - Render select menus in MessageComponentRow instead of placeholder text - Add DiscordStringSelectMenu preview in MessagePreview - Add flow_source_id to selectMenuOptionSchema for option values - Add StringSelectComponent conversion in backend convert.go --- kite-service/pkg/message/convert.go | 39 +++ .../message/MessageComponentRow.tsx | 17 +- .../message/MessageComponentSelectMenu.tsx | 323 ++++++++++++++++++ .../message/MessageComponentsSection.tsx | 11 +- .../src/components/message/MessagePreview.tsx | 21 ++ kite-web/src/lib/message/schema.ts | 1 + kite-web/src/lib/message/schemaRestore.ts | 1 + 7 files changed, 409 insertions(+), 4 deletions(-) create mode 100644 kite-web/src/components/message/MessageComponentSelectMenu.tsx diff --git a/kite-service/pkg/message/convert.go b/kite-service/pkg/message/convert.go index e2be640c..51beb6a4 100644 --- a/kite-service/pkg/message/convert.go +++ b/kite-service/pkg/message/convert.go @@ -226,11 +226,50 @@ func (c *ComponentData) ToComponent(opts ConvertOptions) discord.InteractiveComp Disabled: c.Disabled, CustomID: customID, } + case int(discord.StringSelectComponentType): + var customID discord.ComponentID + if opts.ComponentIDFactory != nil { + customID = opts.ComponentIDFactory(c) + } else { + customID = discord.ComponentID(c.FlowSourceID) + } + + options := make([]discord.SelectOption, len(c.Options)) + for i, opt := range c.Options { + options[i] = opt.ToSelectOption() + } + + return &discord.StringSelectComponent{ + CustomID: customID, + Placeholder: c.Placeholder, + Disabled: c.Disabled, + Options: options, + ValueLimits: [2]int{c.MinValues, c.MaxValues}, + } } return nil } +func (o *ComponentSelectOptionData) ToSelectOption() discord.SelectOption { + if o == nil { + return discord.SelectOption{} + } + + var emoji *discord.ComponentEmoji + if o.Emoji != nil { + emoji = o.Emoji.ToEmoji() + } + + return discord.SelectOption{ + Label: o.Label, + Value: o.FlowSourceID, + Description: o.Description, + Emoji: emoji, + Default: o.Default, + } +} + func (e *ComponentEmojiData) ToEmoji() *discord.ComponentEmoji { if e == nil { return nil diff --git a/kite-web/src/components/message/MessageComponentRow.tsx b/kite-web/src/components/message/MessageComponentRow.tsx index 3b4e9e0f..2c136d79 100644 --- a/kite-web/src/components/message/MessageComponentRow.tsx +++ b/kite-web/src/components/message/MessageComponentRow.tsx @@ -11,6 +11,7 @@ import { import { Button } from "../ui/button"; import { getUniqueId } from "@/lib/utils"; import MessageComponentButton from "./MessageComponentButton"; +import MessageComponentSelectMenu from "./MessageComponentSelectMenu"; export default function MessageComponentRow({ rowIndex, @@ -30,6 +31,9 @@ export default function MessageComponentRow({ const isButtonRow = useCurrentMessage((state) => state.components[rowIndex].components.every((c) => c.type === 2) ); + const isSelectMenuRow = useCurrentMessage((state) => + state.components[rowIndex].components.some((c) => c.type === 3) + ); const [moveUp, moveDown, duplicate, remove] = useCurrentMessage( useShallow((state) => [ state.moveComponentRowUp, @@ -122,9 +126,20 @@ export default function MessageComponentRow({ + ) : isSelectMenuRow ? ( + <> + {components.map((id, i) => ( + + ))} + ) : (
- select menus aren't supported yet + Unknown component type
)} diff --git a/kite-web/src/components/message/MessageComponentSelectMenu.tsx b/kite-web/src/components/message/MessageComponentSelectMenu.tsx new file mode 100644 index 00000000..615ca10c --- /dev/null +++ b/kite-web/src/components/message/MessageComponentSelectMenu.tsx @@ -0,0 +1,323 @@ +import { useCurrentFlow, useCurrentMessage } from "@/lib/message/state"; +import { useShallow } from "zustand/react/shallow"; +import { Card } from "../ui/card"; +import MessageCollapsibleSection from "./MessageCollapsibleSection"; +import { + ChevronDownIcon, + ChevronUpIcon, + CopyIcon, + TrashIcon, + PlusIcon, +} from "lucide-react"; +import MessageInput from "./MessageInput"; +import { useCallback, useMemo } from "react"; +import MessageEmojiPicker from "./MessageEmojiPicker"; +import FlowPreview from "../flow/FlowPreview"; +import FlowDialog from "../flow/FlowDialog"; +import { FlowData } from "@/lib/flow/dataSchema"; +import { getUniqueId } from "@/lib/utils"; +import { Button } from "../ui/button"; + +const initialFlow = { + nodes: [ + { + id: getUniqueId().toString(), + position: { x: 0, y: 0 }, + data: {}, + type: "entry_component_select", + }, + ], + edges: [], +}; + +export default function MessageComponentSelectMenu({ + rowIndex, + compIndex, + disableFlowEditor, +}: { + rowIndex: number; + compIndex: number; + disableFlowEditor?: boolean; +}) { + const selectMenu = useCurrentMessage((state) => + state.getSelectMenu(rowIndex, compIndex) + ); + + const [placeholder, setPlaceholder] = useCurrentMessage( + useShallow((state) => [ + state.getSelectMenu(rowIndex, compIndex)?.placeholder || "", + state.setSelectMenuPlaceholder, + ]) + ); + + const [disabled, setDisabled] = useCurrentMessage( + useShallow((state) => [ + state.getSelectMenu(rowIndex, compIndex)?.disabled, + state.setSelectMenuDisabled, + ]) + ); + + const options = useCurrentMessage( + useShallow((state) => + (state.getSelectMenu(rowIndex, compIndex)?.options || []).map((o) => o.id) + ) + ); + + const [ + addOption, + clearOptions, + moveOptionUp, + moveOptionDown, + duplicateOption, + deleteOption, + ] = useCurrentMessage( + useShallow((state) => [ + state.addSelectMenuOption, + state.clearSelectMenuOptions, + state.moveSelectMenuOptionUp, + state.moveSelectMenuOptionDown, + state.duplicateSelectMenuOption, + state.deleteSelectMenuOption, + ]) + ); + + const [setOptionLabel, setOptionDescription, setOptionEmoji] = + useCurrentMessage( + useShallow((state) => [ + state.setSelectMenuOptionLabel, + state.setSelectMenuOptionDescription, + state.setSelectMenuOptionEmoji, + ]) + ); + + const flowSourceId = useCurrentMessage( + (state) => state.getSelectMenu(rowIndex, compIndex)?.flow_source_id + ); + + const [flowData, replaceFlow] = useCurrentFlow( + useShallow((s) => [s.getFlow(flowSourceId || ""), s.replaceFlow]) + ); + + const onFlowDialogClose = useCallback( + (d: FlowData) => { + if (flowSourceId) { + replaceFlow(flowSourceId, d); + } + }, + [replaceFlow, flowSourceId] + ); + + const handleAddOption = useCallback(() => { + addOption(rowIndex, compIndex, { + id: getUniqueId(), + label: `Option ${options.length + 1}`, + flow_source_id: getUniqueId().toString(), + }); + }, [addOption, rowIndex, compIndex, options.length]); + + if (!selectMenu) { + return
; + } + + return ( + + } + > +
+
+ setPlaceholder(rowIndex, compIndex, v || undefined)} + validationPath={`components.${rowIndex}.components.${compIndex}.placeholder`} + placeholders + /> +
+
+ setDisabled(rowIndex, compIndex, v || undefined)} + validationPath={`components.${rowIndex}.components.${compIndex}.disabled`} + /> +
+
+ + + {options.map((optionId, optionIndex) => ( + moveOptionUp(rowIndex, compIndex, optionIndex)} + onMoveDown={() => moveOptionDown(rowIndex, compIndex, optionIndex)} + onDuplicate={() => duplicateOption(rowIndex, compIndex, optionIndex)} + onDelete={() => deleteOption(rowIndex, compIndex, optionIndex)} + setLabel={(label) => + setOptionLabel(rowIndex, compIndex, optionIndex, label) + } + setDescription={(desc) => + setOptionDescription(rowIndex, compIndex, optionIndex, desc) + } + setEmoji={(emoji) => + setOptionEmoji(rowIndex, compIndex, optionIndex, emoji) + } + /> + ))} +
+ + +
+
+ + {!disableFlowEditor && ( + + {}} /> + + )} +
+
+ ); +} + +function SelectMenuOption({ + rowIndex, + compIndex, + optionIndex, + optionCount, + onMoveUp, + onMoveDown, + onDuplicate, + onDelete, + setLabel, + setDescription, + setEmoji, +}: { + rowIndex: number; + compIndex: number; + optionIndex: number; + optionCount: number; + onMoveUp: () => void; + onMoveDown: () => void; + onDuplicate: () => void; + onDelete: () => void; + setLabel: (label: string) => void; + setDescription: (description: string | undefined) => void; + setEmoji: (emoji: { id?: string; name: string; animated: boolean } | undefined) => void; +}) { + const option = useCurrentMessage((state) => { + const menu = state.getSelectMenu(rowIndex, compIndex); + return menu?.options?.[optionIndex]; + }); + + if (!option) { + return null; + } + + return ( + + + {optionIndex > 0 && ( + + )} + {optionIndex < optionCount - 1 && ( + + )} + {optionCount < 25 && ( + + )} + + + } + > +
+ setEmoji(v)} + /> + setLabel(v)} + validationPath={`components.${rowIndex}.components.${compIndex}.options.${optionIndex}.label`} + /> +
+ setDescription(v || undefined)} + validationPath={`components.${rowIndex}.components.${compIndex}.options.${optionIndex}.description`} + /> +
+
+ ); +} diff --git a/kite-web/src/components/message/MessageComponentsSection.tsx b/kite-web/src/components/message/MessageComponentsSection.tsx index 80154d05..dd303b9c 100644 --- a/kite-web/src/components/message/MessageComponentsSection.tsx +++ b/kite-web/src/components/message/MessageComponentsSection.tsx @@ -28,7 +28,7 @@ export default function MessageComponentsSection({ }); }, [components, addRow]); - /* const addSelectMenuRow = useCallback(() => { + const addSelectMenuRow = useCallback(() => { if (components.length >= 5) return; addRow({ id: getUniqueId(), @@ -37,11 +37,15 @@ export default function MessageComponentsSection({ { id: getUniqueId(), type: 3, - options: [], + placeholder: "", + options: [ + { id: getUniqueId(), label: "Option 1", flow_source_id: getUniqueId().toString() }, + ], + flow_source_id: getUniqueId().toString(), }, ], }); - }, [components, addRow]); */ + }, [components, addRow]); return ( + diff --git a/kite-web/src/components/message/MessagePreview.tsx b/kite-web/src/components/message/MessagePreview.tsx index 80a8872a..3d2e7086 100644 --- a/kite-web/src/components/message/MessagePreview.tsx +++ b/kite-web/src/components/message/MessagePreview.tsx @@ -16,6 +16,8 @@ import { DiscordImageAttachment, DiscordMessage, DiscordMessages, + DiscordStringSelectMenu, + DiscordStringSelectMenuOption, DiscordVideoAttachment, } from "@skyra/discord-components-react"; import MessageMarkdown from "./MessageMarkdown"; @@ -141,6 +143,25 @@ export default function MessagePreview({ > {comp.label} + ) : comp.type === 3 ? ( + + {comp.options.map((opt) => ( + + ))} + ) : null )} diff --git a/kite-web/src/lib/message/schema.ts b/kite-web/src/lib/message/schema.ts index a2b46cc1..9a3adb4d 100644 --- a/kite-web/src/lib/message/schema.ts +++ b/kite-web/src/lib/message/schema.ts @@ -267,6 +267,7 @@ export const selectMenuOptionSchema = z.object({ label: z.string().min(1).max(100), description: z.optional(z.string().min(1).max(100)), emoji: z.optional(emojiSchema), + flow_source_id: z.string().default(() => getUniqueId().toString()), }); export type MessageComponentSelectMenuOption = z.infer< diff --git a/kite-web/src/lib/message/schemaRestore.ts b/kite-web/src/lib/message/schemaRestore.ts index 6ebaa9cb..74c9407c 100644 --- a/kite-web/src/lib/message/schemaRestore.ts +++ b/kite-web/src/lib/message/schemaRestore.ts @@ -270,6 +270,7 @@ export const selectMenuOptionSchema = z.object({ label: z.preprocess((d) => d ?? undefined, z.string().default("")), description: z.preprocess((d) => d || undefined, z.optional(z.string())), emoji: z.preprocess((d) => d ?? undefined, z.optional(emojiSchema)), + flow_source_id: z.string().default(() => getUniqueId().toString()), }); export type MessageComponentSelectMenuOption = z.infer<