@nyaruka/temba-components 0.135.9 → 0.136.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/demo/components/webchat/example.html +4 -2
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1351 -322
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +2 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +2 -6
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +29 -1
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +229 -5
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +320 -1
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +30 -8
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -1
- package/out-tsc/src/simulator/Simulator.js +1861 -0
- package/out-tsc/src/simulator/Simulator.js.map +1 -0
- package/out-tsc/src/store/AppState.js +66 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils.js +48 -0
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +2 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-appstate-node-sorting.test.js +430 -0
- package/out-tsc/test/temba-appstate-node-sorting.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +0 -9
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +262 -1
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +3 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +3 -1
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-simulator.test.js +642 -0
- package/out-tsc/test/temba-simulator.test.js.map +1 -0
- package/out-tsc/test/utils.test.js +1 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/screenshots/truth/simulator/after-message-sent.png +0 -0
- package/screenshots/truth/simulator/after-reset.png +0 -0
- package/screenshots/truth/simulator/attachment-menu.png +0 -0
- package/screenshots/truth/simulator/context-expanded.png +0 -0
- package/screenshots/truth/simulator/context-explorer-open.png +0 -0
- package/screenshots/truth/simulator/event-info.png +0 -0
- package/screenshots/truth/simulator/image-attachment.png +0 -0
- package/screenshots/truth/simulator/open-initial.png +0 -0
- package/screenshots/truth/simulator/quick-replies.png +0 -0
- package/src/Icons.ts +2 -1
- package/src/display/FloatingTab.ts +2 -7
- package/src/flow/CanvasNode.ts +30 -1
- package/src/flow/Editor.ts +246 -4
- package/src/flow/Plumber.ts +371 -2
- package/src/interfaces.ts +2 -1
- package/src/layout/FloatingWindow.ts +37 -12
- package/src/simulator/Simulator.ts +2061 -0
- package/src/store/AppState.ts +109 -0
- package/src/utils.ts +53 -0
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/route.svg +1 -0
- package/static/svg/work/used/route.svg +3 -0
- package/temba-modules.ts +2 -0
- package/test/temba-appstate-node-sorting.test.ts +506 -0
- package/test/temba-floating-tab.test.ts +0 -11
- package/test/temba-flow-editor.test.ts +298 -1
- package/test/temba-flow-plumber-connections.test.ts +4 -1
- package/test/temba-flow-plumber.test.ts +4 -1
- package/test/temba-simulator.test.ts +866 -0
- package/test/utils.test.ts +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Simulator.js","sourceRoot":"","sources":["../../../src/simulator/Simulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { RapidElement } from '../RapidElement';\nimport { FloatingWindow } from '../layout/FloatingWindow';\nimport { css, PropertyValueMap } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { postJSON, fromCookie } from '../utils';\nimport { getStore } from '../store/Store';\nimport { CustomEventType } from '../interfaces';\n\n// test attachment URLs\nconst TEST_IMAGES = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_a.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_b.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_c.jpg',\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_image_d.jpg'\n];\n\nconst TEST_VIDEOS = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_video_a.mp4'\n];\n\nconst TEST_AUDIO = [\n 'https://s3.amazonaws.com/floweditor-assets.temba.io/simulator/sim_audio_a.mp3'\n];\n\nconst TEST_LOCATIONS = [\n 'geo:47.6062,-122.3321', // Seattle\n 'geo:-0.1807,-78.4678', // Quito\n 'geo:-2.9001,-79.0059', // Cuenca\n 'geo:-1.9536,30.0606' // Kigali\n];\n\ninterface Contact {\n uuid: string;\n name?: string;\n urns: string[];\n fields?: { [key: string]: any };\n groups?: any[];\n language?: string;\n status?: string;\n created_on?: string;\n}\n\ninterface Session {\n environment: any;\n runs: any[];\n status: string;\n trigger: any;\n wait?: any;\n}\n\ninterface Message {\n uuid: string;\n text?: string;\n urn: string;\n attachments?: string[];\n quick_replies?: any[];\n}\n\ninterface Event {\n type: string;\n created_on: string;\n msg?: Message;\n [key: string]: any;\n}\n\ninterface RunContext {\n session: Session;\n events: Event[];\n context?: any;\n contact?: Contact;\n}\n\ninterface SimulatorSize {\n phoneWidth: number;\n phoneHeight: number;\n phoneTotalHeight: number;\n phoneScreenHeight: number;\n contextWidth: number;\n contextHeight: number;\n contextOffset: number;\n optionPaneWidth: number;\n optionPaneGap: number;\n windowPadding: number;\n cutoutHeight: number;\n cutoutPadding: number;\n cutoutFontSize: number;\n cutoutIslandWidth: number;\n cutoutIslandHeight: number;\n cutoutIslandTop: number;\n}\n\nconst SIMULATOR_SIZES: Record<string, SimulatorSize> = {\n small: {\n phoneWidth: 270,\n phoneHeight: 576,\n phoneTotalHeight: 576,\n phoneScreenHeight: 376,\n contextWidth: 336,\n contextHeight: 416,\n contextOffset: 48,\n optionPaneWidth: 44,\n optionPaneGap: 10,\n windowPadding: 24,\n cutoutHeight: 32,\n cutoutPadding: 12,\n cutoutFontSize: 10,\n cutoutIslandWidth: 80,\n cutoutIslandHeight: 20,\n cutoutIslandTop: 6\n },\n medium: {\n phoneWidth: 300,\n phoneHeight: 720,\n phoneTotalHeight: 720,\n phoneScreenHeight: 470,\n contextWidth: 420,\n contextHeight: 520,\n contextOffset: 60,\n optionPaneWidth: 44,\n optionPaneGap: 12,\n windowPadding: 30,\n cutoutHeight: 40,\n cutoutPadding: 16,\n cutoutFontSize: 12,\n cutoutIslandWidth: 100,\n cutoutIslandHeight: 24,\n cutoutIslandTop: 8\n },\n large: {\n phoneWidth: 360,\n phoneHeight: 864,\n phoneTotalHeight: 864,\n phoneScreenHeight: 564,\n contextWidth: 504,\n contextHeight: 624,\n contextOffset: 72,\n optionPaneWidth: 44,\n optionPaneGap: 14,\n windowPadding: 36,\n cutoutHeight: 50,\n cutoutPadding: 20,\n cutoutFontSize: 14,\n cutoutIslandWidth: 120,\n cutoutIslandHeight: 30,\n cutoutIslandTop: 10\n }\n};\n\nexport class Simulator extends RapidElement {\n static get styles() {\n return css`\n :host {\n /* size-specific dimensions are set dynamically via inline styles */\n --phone-width: 300px;\n --phone-total-height: 720px;\n --context-width: 420px;\n --context-offset: 60px;\n --option-pane-width: 44px;\n --option-pane-gap: 12px;\n --window-padding: 30px;\n --phone-screen-height: 470px;\n --context-height: 520px;\n --context-closed-left: 332px;\n --animation-time: 200ms;\n }\n\n .phone-simulator {\n padding-left: calc(var(--context-width) + var(--context-offset));\n padding-top: var(--window-padding);\n padding-bottom: var(--window-padding);\n position: relative;\n display: flex;\n align-items: flex-start;\n }\n\n .option-pane {\n margin-top: var(--window-padding);\n margin-left: var(--option-pane-gap);\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 6px;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n border-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n pointer-events: all;\n }\n .option-btn {\n background: rgba(255, 255, 255, 0.1);\n border: none;\n border-radius: 12px;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all var(--animation-time) ease;\n color: white;\n }\n .option-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n transform: scale(1.05);\n }\n .option-btn:active {\n transform: scale(0.95);\n }\n .option-btn.active {\n background: var(--color-primary-dark);\n color: white;\n }\n .option-btn.active:hover {\n background: var(--color-primary-dark);\n }\n\n .phone-frame {\n width: var(--phone-width);\n border-radius: 40px;\n border: 6px solid #1f2937;\n box-shadow: 0 0px 30px rgba(0, 0, 0, 0.4);\n background: #000;\n position: relative;\n overflow: hidden;\n z-index: 2;\n }\n\n .context-explorer {\n width: var(--context-width);\n height: var(--context-height);\n border-top-left-radius: 16px;\n border-bottom-left-radius: 16px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n position: absolute;\n left: var(--context-closed-left);\n top: calc(var(--window-padding) + 40px);\n z-index: 1;\n font-size: 13px;\n color: #374151;\n transition: left calc(var(--animation-time) * 1.5) ease-out,\n opacity calc(var(--animation-time) * 1.5) ease-out;\n opacity: 0;\n pointer-events: none;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(10px);\n display: flex;\n flex-direction: column;\n padding: 12px;\n }\n\n .context-gutter {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 6px;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: 4px;\n margin-right: 32px;\n margin-top: 8px;\n flex-shrink: 0;\n }\n\n .context-gutter-btn {\n width: 14px;\n height: 14px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border-radius: 6px;\n transition: background var(--animation-time) ease;\n color: rgba(255, 255, 255, 0.6);\n padding: 4px;\n }\n\n .context-gutter-btn:hover {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255, 255, 255, 0.9);\n }\n\n .context-gutter-btn.active {\n color: #c084fc;\n }\n\n .context-gutter-spacer {\n flex: 1;\n }\n\n .context-explorer-scroll {\n scrollbar-color: rgba(255, 255, 255, 0.3) #4a4a4a;\n scrollbar-width: thin;\n height: 100%;\n overflow-y: scroll;\n padding-right: 10px;\n margin-right: 30px;\n flex-grow: 1;\n }\n\n .context-explorer-bleed {\n height: 100%;\n width: 0px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar {\n width: 18px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-track {\n background: rgba(0, 0, 0, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 4px;\n }\n\n .context-explorer-scroll::-webkit-scrollbar-thumb:hover {\n background: rgba(255, 255, 255, 0.5);\n }\n\n .context-explorer.open {\n left: var(--context-offset);\n opacity: 1;\n pointer-events: auto;\n }\n\n .context-item {\n display: flex;\n align-items: flex-start;\n padding: 2px 4px;\n cursor: pointer;\n user-select: none;\n }\n\n .context-item:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n .context-item-expandable {\n display: flex;\n align-items: center;\n }\n\n .context-expand-icon {\n width: 16px;\n display: inline-block;\n text-align: center;\n flex-shrink: 0;\n transition: transform var(--animation-time) ease;\n color: #ffffff;\n }\n\n .context-expand-icon.expanded {\n transform: rotate(90deg);\n }\n\n .context-key {\n color: #ffffff;\n flex-shrink: 0;\n margin-right: 8px;\n display: flex;\n }\n\n .context-key.has-value {\n color: #e8b5e8;\n }\n\n .context-value {\n color: #aaa;\n flex: 1;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .context-children {\n margin-left: 16px;\n }\n\n .context-copy-icon {\n opacity: 0;\n margin-left: 4px;\n transition: opacity var(--animation-time) ease;\n cursor: pointer;\n color: #ccc;\n }\n\n .context-item:hover .context-copy-icon {\n opacity: 1;\n }\n\n .context-toast {\n position: absolute;\n bottom: 60px;\n left: 50%;\n transform: translateX(-50%);\n background: #666;\n color: white;\n padding: 12px 12px;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n font-size: 13px;\n z-index: 10;\n animation: slideInUp var(--animation-time) ease-out;\n }\n\n .context-toast .expression {\n color: #e8b5e8;\n font-weight: 600;\n }\n\n @keyframes slideInUp {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .phone-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 10;\n cursor: grab;\n }\n .phone-notch {\n background: transparent;\n height: var(--cutout-height);\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 var(--cutout-padding);\n }\n .phone-notch::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: linear-gradient(\n to bottom,\n rgba(0, 0, 0, 0.3) 0%,\n rgba(0, 0, 0, 0.2) 50%,\n transparent 100%\n );\n z-index: -1;\n }\n .dynamic-island {\n top: var(--cutout-island-top);\n left: 50%;\n\n width: var(--cutout-island-width);\n height: var(--cutout-island-height);\n background: #000;\n border-radius: calc(var(--cutout-island-height) / 1.5);\n z-index: 1;\n }\n .phone-notch .time {\n color: #000;\n font-size: var(--cutout-font-size);\n font-weight: 600;\n }\n .phone-notch .status-icons {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n .phone-notch .status-icons span {\n color: #000;\n font-size: var(--cutout-font-size);\n }\n .phone-header {\n background: transparent;\n padding: 10px 15px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n cursor: move;\n user-select: none;\n border-bottom: none;\n pointer-events: all;\n }\n\n .phone-screen {\n background: white;\n padding: 15px;\n padding-top: calc(var(--cutout-height) + 10px);\n padding-bottom: 60px;\n height: var(--phone-screen-height);\n overflow-y: scroll;\n display: flex;\n flex-direction: column;\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\n scrollbar-width: thin;\n }\n\n .phone-screen::-webkit-scrollbar {\n width: 8px;\n }\n\n .phone-screen::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .phone-screen::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n }\n\n .phone-screen::-webkit-scrollbar-thumb:hover {\n background: rgba(0, 0, 0, 0.3);\n }\n\n @keyframes messageAppear {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 70% {\n opacity: 1;\n transform: scale(1.05);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n .message {\n padding: 10px 14px;\n margin-bottom: 8px;\n border-radius: 18px;\n max-width: 70%;\n font-size: 13px;\n line-height: 1.2;\n }\n .message.animated {\n animation: messageAppear var(--animation-time) ease-out forwards;\n opacity: 0;\n }\n .message.incoming {\n background: #e5e5ea;\n color: #000;\n margin-right: auto;\n border-bottom-left-radius: 4px;\n }\n .message.outgoing {\n background: #007aff;\n color: white;\n margin-left: auto;\n text-align: left;\n border-bottom-right-radius: 4px;\n }\n .attachment-wrapper {\n max-width: 70%;\n margin-bottom: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n .attachment-wrapper.incoming {\n margin-right: auto;\n align-items: flex-start;\n }\n .attachment-wrapper.outgoing {\n margin-left: auto;\n align-items: flex-end;\n }\n .attachment-wrapper.animated {\n animation: messageAppear var(--animation-time) ease-out forwards;\n opacity: 0;\n }\n .attachment {\n border-radius: 12px;\n overflow: hidden;\n max-width: 100%;\n }\n .attachment img {\n max-width: 100%;\n display: block;\n border-radius: 12px;\n }\n .attachment video {\n max-width: 100%;\n display: block;\n border-radius: 12px;\n }\n .attachment-audio {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px;\n background: white;\n border: 1px solid #e5e5ea;\n border-radius: 12px;\n min-width: 160px;\n }\n .attachment-wrapper.outgoing .attachment-audio {\n background: white;\n border: none;\n }\n .attachment-audio audio {\n flex: 1;\n max-height: 30px;\n }\n .attachment-location {\n border-radius: 12px;\n overflow: hidden;\n }\n .event-info {\n text-align: center;\n font-size: 11px;\n color: #8e8e93;\n margin: 4px 0;\n padding: 0 10px;\n line-height: 1.3;\n }\n .event-info.animated {\n animation: messageAppear var(--animation-time) ease-out forwards;\n opacity: 0;\n }\n .message-input {\n background: linear-gradient(\n to top,\n rgba(0, 0, 0, 0.1) 0%,\n rgba(0, 0, 0, 0.05) 70%,\n transparent 100%\n );\n padding: 8px 12px;\n border-top: none;\n display: flex;\n align-items: center;\n gap: 8px;\n position: absolute;\n bottom: 0px;\n left: 0px;\n right: 0px;\n z-index: 10;\n }\n .message-input input {\n flex: 1;\n border: 1px solid #c6c6c8;\n border-radius: 20px;\n padding: 8px 15px;\n font-size: 15px;\n margin-bottom: 5px;\n background: white;\n border: none;\n outline: none;\n }\n .message-input input::placeholder {\n color: #8e8e93;\n }\n .attachment-button {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n flex-shrink: 0;\n margin-bottom: 5px;\n transition: all var(--animation-time) ease;\n color: #000;\n }\n .attachment-button:hover {\n background: #f8f8f8ff;\n transform: scale(1.05);\n }\n .attachment-button:active {\n transform: scale(0.95);\n }\n .attachment-menu {\n position: absolute;\n bottom: 55px;\n left: 12px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n opacity: 0;\n pointer-events: none;\n transform: translateY(10px);\n transition: opacity var(--animation-time) ease, transform 0.2s ease;\n z-index: 20;\n }\n .attachment-menu.open {\n opacity: 1;\n pointer-events: all;\n transform: translateY(0);\n }\n .attachment-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n cursor: pointer;\n transition: background var(--animation-time) ease;\n white-space: nowrap;\n font-size: 14px;\n color: #1f2937;\n }\n .attachment-menu-item:hover {\n background: #f3f4f6;\n }\n .attachment-menu-item temba-icon {\n color: #007aff;\n }\n .quick-replies {\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n gap: 8px;\n margin-top: 4px;\n margin-bottom: 8px;\n }\n .quick-reply-btn {\n background: white;\n color: #007aff;\n border: 1px solid #007aff;\n border-radius: 18px;\n padding: 4px 8px;\n font-size: 11px;\n cursor: pointer;\n transition: all var(--animation-time) ease;\n white-space: nowrap;\n }\n .quick-reply-btn:hover {\n background: #007aff;\n color: white;\n cursor: pointer;\n }\n .quick-reply-btn:active {\n transform: scale(0.95);\n }\n .quick-reply-btn.animated {\n animation: messageAppear var(--animation-time) ease-out forwards;\n opacity: 0;\n }\n `;\n }\n\n @property({ type: String })\n flow = '';\n\n @property({ type: String })\n endpoint = '';\n\n @property({ type: Number })\n animationTime = 200;\n\n @fromCookie('simulator-size', 'small')\n size: 'small' | 'medium' | 'large';\n\n @property({ type: Array })\n private events: Event[] = [];\n\n private previousEventCount = 0;\n\n @property({ type: Object })\n private session: Session | null = null;\n\n @property({ type: Object })\n private context: any = null;\n\n @property({ type: Object })\n private contact: Contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n @property({ type: Boolean })\n private sprinting = false;\n\n @property({ type: String })\n private inputValue = '';\n\n @fromCookie('simulator-follow', true)\n private following: boolean;\n\n @fromCookie('simulator-context-open', false)\n private contextExplorerOpen: boolean;\n\n @property({ type: Object })\n private expandedPaths: Set<string> = new Set();\n\n @property({ type: String })\n private copiedExpression = '';\n\n @property({ type: String })\n private toastMessage = '';\n\n @property({ type: Boolean })\n private showAllKeys = true;\n\n private previousWindowWidth = 0;\n\n @property({ type: Array })\n private currentQuickReplies: any[] = [];\n\n @property({ type: Boolean })\n private isVisible = false;\n\n @property({ type: Boolean })\n private attachmentMenuOpen = false;\n\n private boundClickOutsideHandler: ((event: MouseEvent) => void) | null = null;\n\n // attachment cycling indices - initialized randomly\n private imageIndex = Math.floor(Math.random() * TEST_IMAGES.length);\n private videoIndex = Math.floor(Math.random() * TEST_VIDEOS.length);\n private audioIndex = Math.floor(Math.random() * TEST_AUDIO.length);\n private locationIndex = Math.floor(Math.random() * TEST_LOCATIONS.length);\n\n // method to reset attachment indices for testing\n public resetAttachmentIndices() {\n this.imageIndex = 2;\n this.videoIndex = 0;\n this.audioIndex = 0;\n this.locationIndex = 0;\n }\n\n private get sizeConfig(): SimulatorSize {\n return SIMULATOR_SIZES[this.size] || SIMULATOR_SIZES.medium;\n }\n\n private get windowWidth(): number {\n const config = this.sizeConfig;\n return (\n config.contextWidth +\n config.phoneWidth +\n config.optionPaneWidth +\n config.optionPaneGap +\n config.contextOffset\n );\n }\n\n private get leftBoundaryMargin(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset;\n }\n\n private get contextClosedLeft(): number {\n const config = this.sizeConfig;\n return config.contextWidth + config.contextOffset - config.phoneWidth;\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('flow') && this.flow) {\n this.endpoint = `/flow/simulate/${this.flow}/`;\n }\n\n // handle attachment menu click outside listener\n if (changes.has('attachmentMenuOpen')) {\n if (this.attachmentMenuOpen) {\n // create bound handler if it doesn't exist\n if (!this.boundClickOutsideHandler) {\n this.boundClickOutsideHandler =\n this.handleClickOutsideAttachmentMenu.bind(this);\n }\n // add listener when menu opens\n setTimeout(() => {\n document.addEventListener('click', this.boundClickOutsideHandler);\n }, 0);\n } else {\n // remove listener when menu closes\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n }\n\n // update floating window boundaries when size changes\n if (changes.has('size')) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n // use the stored previous width since phoneWindow.width has already been updated\n const oldWidth = this.previousWindowWidth || phoneWindow.width;\n const oldRight = phoneWindow.left + oldWidth;\n\n const config = this.sizeConfig;\n const newWidth = this.windowWidth;\n\n // store current width for next size change\n this.previousWindowWidth = newWidth;\n\n // update dimensions and boundaries\n phoneWindow.width = newWidth;\n phoneWindow.leftBoundaryMargin = this.leftBoundaryMargin;\n phoneWindow.topBoundaryMargin = config.windowPadding;\n phoneWindow.bottomBoundaryMargin = config.windowPadding;\n\n // keep right edge in same position by adjusting left\n let newLeft = oldRight - newWidth;\n\n // apply same boundary logic as FloatingWindow.handleMouseMove\n const padding = 20;\n const minLeft = padding - this.leftBoundaryMargin;\n const maxLeft =\n window.innerWidth -\n newWidth -\n padding +\n phoneWindow.rightBoundaryMargin;\n\n // clamp to boundaries\n newLeft = Math.max(minLeft, Math.min(newLeft, maxLeft));\n\n phoneWindow.left = newLeft;\n\n // adjust vertical position if needed\n const windowElement = phoneWindow.shadowRoot?.querySelector(\n '.window'\n ) as HTMLElement;\n const currentHeight =\n windowElement?.offsetHeight || config.phoneTotalHeight;\n const maxTop = Math.max(\n padding - config.windowPadding,\n window.innerHeight - currentHeight - padding + config.windowPadding\n );\n\n phoneWindow.top = Math.max(\n padding - config.windowPadding,\n Math.min(phoneWindow.top, maxTop)\n );\n }\n });\n } else {\n // store initial width when first rendered\n if (!this.previousWindowWidth) {\n this.previousWindowWidth = this.windowWidth;\n }\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n // clean up event listener when component is removed\n if (this.boundClickOutsideHandler) {\n document.removeEventListener('click', this.boundClickOutsideHandler);\n }\n }\n\n private handleShow() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n phoneWindow.show();\n this.isVisible = true;\n getStore().getState().setSimulatorActive(true);\n\n // start the simulation if we haven't already\n if (this.events.length === 0) {\n this.startFlow();\n }\n }\n\n private async startFlow() {\n const now = new Date().toISOString();\n\n // set created_on to simulation start time\n this.contact = { ...this.contact, created_on: now };\n\n const body = {\n contact: this.contact,\n trigger: {\n type: 'manual',\n triggered_on: now,\n flow: { uuid: this.flow, name: 'New Chat' },\n params: {}\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n this.updateRunContext(response.json as RunContext);\n } catch (error) {\n console.error('Failed to start simulation:', error);\n this.events = [\n ...this.events,\n {\n type: 'error',\n created_on: now,\n text: 'Failed to start simulation'\n } as any\n ];\n }\n }\n\n private updateRunContext(runContext: RunContext, msgInEvt?: Event) {\n if (msgInEvt) {\n this.events = [...this.events, msgInEvt];\n }\n\n if (runContext.session) {\n this.session = runContext.session;\n\n // update our contact with the latest from the session\n if (runContext.contact) {\n this.contact = runContext.contact;\n }\n }\n\n // store the context from the response\n if (runContext.context) {\n this.context = runContext.context;\n }\n\n if (runContext.events && runContext.events.length > 0) {\n this.events = [...this.events, ...runContext.events];\n\n // extract quick replies from the most recent sprint\n this.currentQuickReplies = [];\n for (const event of runContext.events) {\n if (event.type === 'msg_created' && event.msg?.quick_replies) {\n this.currentQuickReplies = event.msg.quick_replies;\n }\n }\n }\n\n this.sprinting = false;\n this.requestUpdate();\n this.scrollToBottom();\n this.updateActivity();\n }\n\n private updateActivity() {\n if (!this.session) {\n return;\n }\n\n const pathCounts: { [key: string]: number } = {};\n const nodeCounts: { [nodeUUID: string]: number } = {};\n\n // iterate through all runs to get path segment counts\n for (const run of this.session.runs) {\n if (run.path) {\n for (let i = 0; i < run.path.length - 1; i++) {\n const step = run.path[i];\n const nextStep = run.path[i + 1];\n if (step.exit_uuid && nextStep.node_uuid) {\n const key = step.exit_uuid + ':' + nextStep.node_uuid;\n pathCounts[key] = (pathCounts[key] || 0) + 1;\n }\n }\n }\n\n // set node counts on the last step of any active/waiting runs\n if (run.status === 'active' || run.status === 'waiting') {\n if (run.path && run.path.length > 0) {\n const finalStep = run.path[run.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n nodeCounts[finalStep.node_uuid] =\n (nodeCounts[finalStep.node_uuid] || 0) + 1;\n }\n }\n }\n }\n\n // Update simulator activity in the store\n getStore().getState().updateSimulatorActivity({\n segments: pathCounts,\n nodes: nodeCounts\n });\n\n // Fire follow event if following is enabled\n if (this.following) {\n this.fireFollowEvent();\n }\n }\n\n private fireFollowEvent() {\n if (!this.session || !this.session.runs || this.session.runs.length === 0) {\n return;\n }\n\n // Find the first active or waiting run\n let activeRun = this.session.runs.find(\n (run: any) => run.status === 'active' || run.status === 'waiting'\n );\n\n // If no active/waiting run and simulation has ended, use the first completed run\n if (!activeRun) {\n activeRun = this.session.runs.find(\n (run: any) => run.status === 'completed'\n );\n }\n\n if (activeRun && activeRun.path && activeRun.path.length > 0) {\n const finalStep = activeRun.path[activeRun.path.length - 1];\n if (finalStep && finalStep.node_uuid) {\n this.fireCustomEvent(CustomEventType.FollowSimulation, {\n flowUuid: activeRun.flow?.uuid || this.flow,\n nodeUuid: finalStep.node_uuid\n });\n }\n }\n }\n\n private scrollToBottom() {\n // wait for render, then scroll to bottom\n setTimeout(() => {\n const screen = this.shadowRoot?.querySelector('.phone-screen');\n if (screen) {\n screen.scrollTop = screen.scrollHeight;\n }\n // update previous count after animation completes\n this.previousEventCount = this.events.length;\n\n // return focus to input\n const input = this.shadowRoot?.querySelector(\n '.message-input input'\n ) as HTMLInputElement;\n if (input) {\n input.focus();\n }\n }, 50);\n }\n\n private handleClose() {\n const phoneWindow = this.shadowRoot.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n // phoneWindow.hide();\n\n phoneWindow.handleClose();\n this.isVisible = false;\n getStore().getState().setSimulatorActive(false);\n }\n\n private handleReset() {\n // reset simulation state\n this.events = [];\n this.session = null;\n this.context = null;\n this.inputValue = '';\n this.sprinting = false;\n this.previousEventCount = 0;\n this.currentQuickReplies = [];\n\n // Clear simulator activity data\n getStore().getState().updateSimulatorActivity({\n segments: {},\n nodes: {}\n });\n\n // reset contact to initial state\n this.contact = {\n uuid: 'fb3787ab-2eda-48a0-a2bc-e2ddadec1286',\n urns: ['tel:+12065551212'],\n fields: {},\n groups: [],\n language: 'eng',\n status: 'active',\n created_on: new Date().toISOString()\n };\n\n // restart the flow\n this.startFlow();\n }\n\n private handleToggleFollow() {\n this.following = !this.following;\n }\n\n private handleCycleSize() {\n const sizes: Array<'small' | 'medium' | 'large'> = [\n 'small',\n 'medium',\n 'large'\n ];\n const currentIndex = sizes.indexOf(this.size);\n const nextIndex = (currentIndex + 1) % sizes.length;\n this.size = sizes[nextIndex];\n }\n\n private handleToggleContextExplorer() {\n this.contextExplorerOpen = !this.contextExplorerOpen;\n\n // if opening the context explorer, ensure it's not off-screen\n if (this.contextExplorerOpen) {\n requestAnimationFrame(() => {\n const phoneWindow = this.shadowRoot?.getElementById(\n 'phone-window'\n ) as FloatingWindow;\n if (phoneWindow) {\n const padding = 20;\n const contextExplorerLeft = this.sizeConfig.contextOffset;\n const minWindowLeft = padding - contextExplorerLeft;\n\n if (phoneWindow.left < minWindowLeft) {\n phoneWindow.left = minWindowLeft;\n }\n }\n });\n }\n }\n\n private togglePath(path: string) {\n if (this.expandedPaths.has(path)) {\n this.expandedPaths.delete(path);\n } else {\n this.expandedPaths.add(path);\n }\n this.requestUpdate();\n }\n\n private isExpandable(value: any): boolean {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n\n // check if object has keys other than __default__\n const keys = Object.keys(value).filter((key) => key !== '__default__');\n return keys.length > 0;\n }\n\n private renderContextValue(value: any): TemplateResult | string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'boolean')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'number')\n return html`<span class=\"context-value\">${value}</span>`;\n if (typeof value === 'string')\n return html`<span class=\"context-value\">${value}</span>`;\n if (Array.isArray(value))\n return html`<span class=\"context-value\">[${value.length}]</span>`;\n return '';\n }\n\n private buildExpression(path: string): string {\n return `@${path}`;\n }\n\n private async handleCopyExpression(\n path: string,\n event: Event\n ): Promise<void> {\n event.stopPropagation();\n const expression = this.buildExpression(path);\n try {\n await navigator.clipboard.writeText(expression);\n this.copiedExpression = expression;\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.copiedExpression = '';\n }, 2000);\n } catch (err) {\n console.error('Failed to copy expression:', err);\n }\n }\n\n private handleToggleShowAllKeys() {\n this.showAllKeys = !this.showAllKeys;\n this.toastMessage = this.showAllKeys\n ? 'Showing all keys'\n : 'Filtering out keys without values';\n // clear the toast after 2 seconds\n setTimeout(() => {\n this.toastMessage = '';\n }, 2000);\n }\n\n private renderContextTree(\n obj: any,\n path: string = ''\n ): TemplateResult | TemplateResult[] {\n if (!obj || typeof obj !== 'object') {\n return html``;\n }\n\n let entries = Array.isArray(obj)\n ? obj.map((v, i) => [String(i), v])\n : Object.entries(obj).filter(([key]) => key !== '__default__');\n\n // filter out keys without values if showAllKeys is false\n if (!this.showAllKeys) {\n entries = entries.filter(([, value]) => {\n // keep if expandable (has children)\n if (this.isExpandable(value)) return true;\n // keep if it has a displayable value (not null/undefined)\n if (value === null || value === undefined) return false;\n // keep primitives with values\n return (\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string' ||\n Array.isArray(value)\n );\n });\n }\n\n return html`${entries.map(([key, value]) => {\n const currentPath = path ? `${path}.${key}` : key;\n const isExpanded = this.expandedPaths.has(currentPath);\n const expandable = this.isExpandable(value);\n\n // check if this object has a __default__ value\n let displayValue = value;\n\n if (\n expandable &&\n !Array.isArray(value) &&\n value !== null &&\n typeof value === 'object' &&\n '__default__' in value\n ) {\n displayValue = value.__default__;\n }\n\n return html`\n <div>\n <div\n class=\"context-item ${expandable ? 'context-item-expandable' : ''}\"\n @click=${() => expandable && this.togglePath(currentPath)}\n >\n ${expandable\n ? html`<span\n class=\"context-expand-icon ${isExpanded ? 'expanded' : ''}\"\n >›</span\n >`\n : html`<span class=\"context-expand-icon\"></span>`}\n <span class=\"context-key ${expandable ? 'has-value' : ''}\"\n >${key}\n <temba-icon\n class=\"context-copy-icon\"\n name=\"copy\"\n size=\"0.9\"\n @click=${(e: Event) =>\n this.handleCopyExpression(currentPath, e)}\n ></temba-icon>\n </span>\n ${!isExpanded ? this.renderContextValue(displayValue) : html``}\n </div>\n ${isExpanded\n ? html`<div class=\"context-children\">\n ${this.renderContextTree(value, currentPath)}\n </div>`\n : html``}\n </div>\n `;\n })}`;\n }\n\n private async resume(text: string, attachment?: string) {\n if ((!text && !attachment) || !this.session) {\n return;\n }\n\n this.sprinting = true;\n this.inputValue = '';\n this.currentQuickReplies = [];\n this.attachmentMenuOpen = false;\n\n const now = new Date().toISOString();\n const msgInEvt: Event = {\n uuid: crypto.randomUUID(),\n type: 'msg_received',\n created_on: now,\n msg: {\n uuid: crypto.randomUUID(),\n text: text || '',\n urn: this.contact.urns[0],\n attachments: attachment ? [attachment] : []\n }\n };\n\n // show user's message immediately\n this.events = [...this.events, msgInEvt];\n this.requestUpdate();\n this.scrollToBottom();\n\n const body = {\n session: this.session,\n contact: this.contact,\n resume: {\n type: 'msg',\n event: msgInEvt,\n resumed_on: now\n }\n };\n\n try {\n const response = await postJSON(this.endpoint, body);\n\n // add a small delay before showing the reply to simulate typing\n await new Promise((resolve) => setTimeout(resolve, 400));\n\n // pass null for msgInEvt since we already added it\n this.updateRunContext(response.json as RunContext, null);\n } catch (error) {\n console.error('Failed to resume simulation:', error);\n this.events = [\n ...this.events,\n {\n type: 'error',\n created_on: now,\n text: 'Failed to send message'\n } as any\n ];\n this.sprinting = false;\n }\n }\n\n private handleKeyUp(evt: KeyboardEvent) {\n if (evt.key === 'Enter') {\n const input = evt.target as HTMLInputElement;\n const text = input.value.trim();\n if (text) {\n this.resume(text);\n }\n }\n }\n\n private handleInput(evt: Event) {\n const input = evt.target as HTMLInputElement;\n this.inputValue = input.value;\n }\n\n private handleQuickReply(quickReply: string) {\n if (!this.sprinting) {\n this.resume(quickReply);\n }\n }\n\n private handleToggleAttachmentMenu() {\n this.attachmentMenuOpen = !this.attachmentMenuOpen;\n }\n\n private handleClickOutsideAttachmentMenu(event: MouseEvent) {\n if (!this.attachmentMenuOpen) {\n return;\n }\n\n const menu = this.shadowRoot?.querySelector('.attachment-menu');\n const button = this.shadowRoot?.querySelector('.attachment-button');\n\n if (!menu || !button) {\n return;\n }\n\n // check if click is outside both menu and button\n const clickedInsideMenu = menu.contains(event.target as Node);\n const clickedInsideButton = button.contains(event.target as Node);\n\n if (!clickedInsideMenu && !clickedInsideButton) {\n this.attachmentMenuOpen = false;\n }\n }\n\n private handleSendAttachment(attachmentType: string) {\n let attachment = '';\n switch (attachmentType) {\n case 'image':\n attachment = `image/jpeg:${TEST_IMAGES[this.imageIndex]}`;\n this.imageIndex = (this.imageIndex + 1) % TEST_IMAGES.length;\n break;\n case 'video':\n attachment = `video/mp4:${TEST_VIDEOS[this.videoIndex]}`;\n this.videoIndex = (this.videoIndex + 1) % TEST_VIDEOS.length;\n break;\n case 'audio':\n attachment = `audio/mp3:${TEST_AUDIO[this.audioIndex]}`;\n this.audioIndex = (this.audioIndex + 1) % TEST_AUDIO.length;\n break;\n case 'location':\n attachment = TEST_LOCATIONS[this.locationIndex];\n this.locationIndex = (this.locationIndex + 1) % TEST_LOCATIONS.length;\n break;\n }\n\n if (attachment) {\n this.resume('', attachment);\n }\n }\n\n private getEventDescription(event: Event): string | null {\n switch (event.type) {\n case 'contact_groups_changed': {\n const groups = (event as any).groups_added || [];\n const removedGroups = (event as any).groups_removed || [];\n if (groups.length > 0) {\n const groupNames = groups.map((g: any) => `\"${g.name}\"`).join(', ');\n return `Added to ${groupNames}`;\n }\n if (removedGroups.length > 0) {\n const groupNames = removedGroups\n .map((g: any) => `\"${g.name}\"`)\n .join(', ');\n return `Removed from ${groupNames}`;\n }\n break;\n }\n case 'contact_field_changed': {\n const field = (event as any).field;\n const value = (event as any).value;\n const valueText = value ? value.text || value : '';\n if (field) {\n if (valueText) {\n return `Set contact \"${field.name}\" to \"${valueText}\"`;\n } else {\n return `Cleared contact \"${field.name}\"`;\n }\n }\n break;\n }\n case 'contact_language_changed':\n return `Set preferred language to \"${(event as any).language}\"`;\n case 'contact_name_changed':\n return `Set contact name to \"${(event as any).name}\"`;\n case 'contact_status_changed':\n return `Set status to \"${(event as any).status}\"`;\n case 'contact_urns_changed':\n return `Added a URN for the contact`;\n case 'input_labels_added': {\n const labels = (event as any).labels || [];\n if (labels.length > 0) {\n const labelNames = labels.map((l: any) => `\"${l.name}\"`).join(', ');\n return `Message labeled with ${labelNames}`;\n }\n break;\n }\n case 'run_result_changed':\n return `Set result \"${(event as any).name}\" to \"${\n (event as any).value\n }\"`;\n case 'run_started':\n case 'flow_entered': {\n const flow = (event as any).flow;\n if (flow) {\n return `Entered flow \"${flow.name}\"`;\n }\n break;\n }\n case 'run_ended': {\n const flow = (event as any).flow;\n if (flow) {\n return `Exited flow \"${flow.name}\"`;\n }\n break;\n }\n case 'email_created':\n case 'email_sent': {\n const recipients = (event as any).to || (event as any).addresses || [];\n const subject = (event as any).subject;\n const recipientList = recipients\n .map((r: string) => `\"${r}\"`)\n .join(', ');\n return `Sent email to ${recipientList} with subject \"${subject}\"`;\n }\n case 'broadcast_created': {\n const translations = (event as any).translations;\n const baseLanguage = (event as any).base_language;\n if (translations && translations[baseLanguage]) {\n return `Sent broadcast: \"${translations[baseLanguage].text}\"`;\n }\n return `Sent broadcast`;\n }\n case 'session_triggered': {\n const flow = (event as any).flow;\n if (flow) {\n return `Started somebody else in \"${flow.name}\"`;\n }\n break;\n }\n case 'ticket_opened': {\n const ticket = (event as any).ticket;\n if (ticket && ticket.topic) {\n return `Ticket opened with topic \"${ticket.topic.name}\"`;\n }\n return `Ticket opened`;\n }\n case 'resthook_called':\n return `Triggered flow event \"${(event as any).resthook}\"`;\n case 'webhook_called':\n return `Called ${(event as any).url}`;\n case 'service_called': {\n const service = (event as any).service;\n if (service === 'classifier') {\n return `Called classifier`;\n }\n return `Called ${service}`;\n }\n case 'airtime_transferred': {\n const amount = (event as any).actual_amount;\n const currency = (event as any).currency;\n const recipient = (event as any).recipient;\n if (amount && currency && recipient) {\n return `Transferred ${amount} ${currency} to ${recipient}`;\n }\n break;\n }\n case 'info':\n return (event as any).text;\n case 'warning':\n return `⚠️ ${(event as any).text}`;\n }\n return null;\n }\n\n private renderAlertMessage(\n type: 'error' | 'warning' | 'failure',\n text: string,\n animatedClass: string,\n animationDelay: string\n ): TemplateResult {\n const config = {\n error: {\n icon: '❗',\n bgColor: '#fee2e2',\n textColor: '#991b1b',\n defaultText: 'An error occurred'\n },\n warning: {\n icon: '⚠️',\n bgColor: '#fef3c7',\n textColor: 'rgba(125, 87, 18, 0.8)',\n defaultText: 'A warning occurred'\n },\n failure: {\n icon: '💥',\n bgColor: '#fee2e2',\n textColor: '#991b1b',\n defaultText: 'A failure occurred'\n }\n }[type];\n\n return html`\n <div\n class=\"event-info ${animatedClass}\"\n style=\"display:flex; align-items:center; background: ${config.bgColor}; color: ${config.textColor}; padding: 6px; margin: 4px 12px; border-radius: 8px; animation-delay: ${animationDelay}\"\n >\n <div style=\"padding:4px;margin-right:6px;font-size:15px\">\n ${config.icon}\n </div>\n <div style=\"padding-right:2px;text-align:left\">\n ${text || config.defaultText}\n </div>\n </div>\n `;\n }\n\n private renderAttachment(attachment: string): TemplateResult {\n // parse attachment format: \"type/subtype:url\" or \"geo:lat,long\"\n const parts = attachment.split(':');\n const type = parts[0];\n const content = parts.slice(1).join(':'); // rejoin in case url has colons\n\n if (type === 'geo') {\n // use temba-thumbnail for location to get map image\n return html`\n <div class=\"attachment-location\">\n <temba-thumbnail attachment=\"${attachment}\"></temba-thumbnail>\n </div>\n `;\n } else if (type.startsWith('image/')) {\n // custom image rendering\n return html`\n <div class=\"attachment\">\n <img src=\"${content}\" alt=\"Image attachment\" />\n </div>\n `;\n } else if (type.startsWith('video/')) {\n // custom video rendering\n return html`\n <div class=\"attachment\">\n <video controls>\n <source src=\"${content}\" type=\"${type}\" />\n </video>\n </div>\n `;\n } else if (type.startsWith('audio/')) {\n // custom audio rendering\n return html`\n <div class=\"attachment\">\n <div class=\"attachment-audio\">\n <audio controls>\n <source src=\"${content}\" type=\"${type}\" />\n </audio>\n </div>\n </div>\n `;\n }\n\n // fallback for unknown types\n return html`\n <div class=\"attachment\">\n <span>Attachment</span>\n </div>\n `;\n }\n\n private renderMessages(): TemplateResult {\n if (this.events.length === 0) {\n return html`\n <div class=\"message incoming\">👋 Welcome! Starting simulation...</div>\n `;\n }\n\n const eventTemplates = this.events.map((event, index) => {\n // only animate messages that are new (beyond previous count)\n const isNew = index >= this.previousEventCount;\n const animatedClass = isNew ? 'animated' : '';\n // stagger animations for new messages\n const animationDelay = isNew\n ? `${(index - this.previousEventCount) * 0.2}s`\n : '0s';\n\n if (event.type === 'msg_received' && event.msg) {\n const hasAttachments =\n event.msg.attachments && event.msg.attachments.length > 0;\n const hasText = event.msg.text && event.msg.text.trim().length > 0;\n\n return html`\n ${hasAttachments\n ? html`\n <div\n class=\"attachment-wrapper outgoing ${animatedClass}\"\n style=\"animation-delay: ${animationDelay}\"\n >\n ${event.msg.attachments.map((att: string) =>\n this.renderAttachment(att)\n )}\n </div>\n `\n : html``}\n ${hasText\n ? html`\n <div\n class=\"message outgoing ${animatedClass}\"\n style=\"animation-delay: ${animationDelay}\"\n >\n ${event.msg.text}\n </div>\n `\n : html``}\n `;\n } else if (event.type === 'msg_created' && event.msg) {\n const hasAttachments =\n event.msg.attachments && event.msg.attachments.length > 0;\n const hasText = event.msg.text && event.msg.text.trim().length > 0;\n\n return html`\n ${hasAttachments\n ? html`\n <div\n class=\"attachment-wrapper incoming ${animatedClass}\"\n style=\"animation-delay: ${animationDelay}\"\n >\n ${event.msg.attachments.map((att: string) =>\n this.renderAttachment(att)\n )}\n </div>\n `\n : html``}\n ${hasText\n ? html`\n <div\n class=\"message incoming ${animatedClass}\"\n style=\"animation-delay: ${animationDelay}\"\n >\n ${event.msg.text}\n </div>\n `\n : html``}\n `;\n } else if (event.type === 'failure') {\n return this.renderAlertMessage(\n 'failure',\n (event as any).text,\n animatedClass,\n animationDelay\n );\n } else if (event.type === 'warning') {\n return this.renderAlertMessage(\n 'warning',\n (event as any).text,\n animatedClass,\n animationDelay\n );\n } else if (event.type === 'error') {\n return this.renderAlertMessage(\n 'error',\n (event as any).text,\n animatedClass,\n animationDelay\n );\n } else {\n // check if this is an event we should display\n const description = this.getEventDescription(event);\n if (description) {\n return html`\n <div\n class=\"event-info ${animatedClass}\"\n style=\"animation-delay: ${animationDelay}\"\n >\n ${description}\n </div>\n `;\n }\n }\n return html``;\n });\n\n // render quick replies at the end if we have any from the most recent sprint\n const hasQuickReplies = this.currentQuickReplies.length > 0;\n const quickRepliesAnimationDelay =\n this.events.length >= this.previousEventCount\n ? `${(this.events.length - this.previousEventCount) * 0.2}s`\n : '0s';\n\n return html`\n ${eventTemplates}\n ${hasQuickReplies\n ? html`\n <div\n class=\"quick-replies animated\"\n style=\"animation-delay: ${quickRepliesAnimationDelay}\"\n >\n ${this.currentQuickReplies.map(\n (qr: any) => html`\n <button\n class=\"quick-reply-btn animated\"\n style=\"animation-delay: ${quickRepliesAnimationDelay}\"\n @click=${() => this.handleQuickReply(qr.text)}\n >\n ${qr.text}\n </button>\n `\n )}\n </div>\n `\n : html``}\n `;\n }\n\n protected render(): TemplateResult {\n const config = this.sizeConfig;\n\n // set CSS custom properties dynamically based on size\n const styleVars = `\n --phone-width: ${config.phoneWidth}px;\n --phone-total-height: ${config.phoneTotalHeight}px;\n --context-width: ${config.contextWidth}px;\n --context-offset: ${config.contextOffset}px;\n --option-pane-width: ${config.optionPaneWidth}px;\n --option-pane-gap: ${config.optionPaneGap}px;\n --window-padding: ${config.windowPadding}px;\n --phone-screen-height: ${config.phoneScreenHeight}px;\n --context-height: ${config.contextHeight}px;\n --context-closed-left: ${this.contextClosedLeft}px;\n --cutout-height: ${config.cutoutHeight}px;\n --cutout-padding: ${config.cutoutPadding}px;\n --cutout-font-size: ${config.cutoutFontSize}px;\n --cutout-island-width: ${config.cutoutIslandWidth}px;\n --cutout-island-height: ${config.cutoutIslandHeight}px;\n --cutout-island-top: ${config.cutoutIslandTop}px;\n `;\n\n return html`\n <temba-floating-window\n id=\"phone-window\"\n width=\"${this.windowWidth}\"\n leftBoundaryMargin=\"${this.leftBoundaryMargin}\"\n bottomBoundaryMargin=\"${config.windowPadding}\"\n topBoundaryMargin=\"${config.windowPadding}\"\n height=\"${config.phoneTotalHeight}\"\n top=\"0\"\n chromeless\n >\n <div class=\"phone-simulator\" style=\"${styleVars}\">\n <div\n class=\"context-explorer ${this.contextExplorerOpen ? 'open' : ''}\"\n >\n <div class=\"context-explorer-scroll\">\n ${this.context\n ? this.renderContextTree(this.context)\n : html`<div\n style=\"color: #9ca3af; padding: 8px; text-align: center;\"\n >\n No context available\n </div>`}\n </div>\n <div class=\"context-gutter\">\n <div\n class=\"context-gutter-btn ${this.showAllKeys ? '' : 'active'}\"\n @click=${this.handleToggleShowAllKeys}\n title=\"${this.showAllKeys\n ? 'Show keys with values only'\n : 'Show all keys'}\"\n >\n <temba-icon\n name=\"${this.showAllKeys ? 'filter' : 'filter'}\"\n size=\"1\"\n ></temba-icon>\n </div>\n <div class=\"context-gutter-spacer\"></div>\n <div\n class=\"context-gutter-btn\"\n @click=${this.handleToggleContextExplorer}\n title=\"Close\"\n >\n <temba-icon name=\"x\" size=\"1\"></temba-icon>\n </div>\n </div>\n ${this.copiedExpression\n ? html`<div class=\"context-toast\">\n Copied\n <span class=\"expression\">${this.copiedExpression}</span>\n to the clipboard\n </div>`\n : this.toastMessage\n ? html`<div class=\"context-toast\">${this.toastMessage}</div>`\n : html``}\n </div>\n\n <div\n class=\"phone-frame\"\n style=\"pointer-events: ${this.isVisible ? 'all' : 'none'}\"\n >\n <div class=\"phone-top drag-handle\">\n <div class=\"phone-notch\">\n <div class=\"dynamic-island\"></div>\n </div>\n </div>\n <div class=\"phone-screen\">${this.renderMessages()}</div>\n <div class=\"message-input\">\n <button\n class=\"attachment-button\"\n @click=${this.handleToggleAttachmentMenu}\n ?disabled=${this.sprinting}\n >\n <temba-icon name=\"plus\" size=\"1.5\"></temba-icon>\n </button>\n <input\n type=\"text\"\n placeholder=\"Enter Message\"\n .value=${this.inputValue}\n @input=${this.handleInput}\n @keyup=${this.handleKeyUp}\n ?disabled=${this.sprinting}\n />\n <div\n class=\"attachment-menu ${this.attachmentMenuOpen ? 'open' : ''}\"\n >\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('image')}\n >\n <temba-icon name=\"attachment_image\" size=\"1.2\"></temba-icon>\n <span>Image</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('video')}\n >\n <temba-icon name=\"attachment_video\" size=\"1.2\"></temba-icon>\n <span>Video</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('audio')}\n >\n <temba-icon name=\"attachment_audio\" size=\"1.2\"></temba-icon>\n <span>Audio</span>\n </div>\n <div\n class=\"attachment-menu-item\"\n @click=${() => this.handleSendAttachment('location')}\n >\n <temba-icon\n name=\"attachment_location\"\n size=\"1.2\"\n ></temba-icon>\n <span>Location</span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"option-pane\">\n <button class=\"option-btn\" @click=${this.handleClose} title=\"Close\">\n <temba-icon name=\"x\" size=\"1.5\"></temba-icon>\n </button>\n <button\n class=\"option-btn ${this.following ? 'active' : ''}\"\n @click=${this.handleToggleFollow}\n title=\"${this.following ? 'Following' : 'Follow'}\"\n >\n <temba-icon name=\"follow\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn ${this.contextExplorerOpen ? 'active' : ''}\"\n @click=${this.handleToggleContextExplorer}\n title=\"Context Explorer\"\n >\n <temba-icon name=\"expressions\" size=\"1.5\"></temba-icon>\n </button>\n\n <button\n class=\"option-btn\"\n @click=${this.handleCycleSize}\n title=\"Size: ${this.size}\"\n >\n ${this.size === 'small'\n ? 'S'\n : this.size === 'medium'\n ? 'M'\n : 'L'}\n </button>\n\n <button class=\"option-btn\" @click=${this.handleReset} title=\"Reset\">\n <temba-icon name=\"delete\" size=\"1.5\"></temba-icon>\n </button>\n </div>\n </div>\n </temba-floating-window>\n\n <temba-floating-tab\n id=\"phone-tab\"\n icon=\"simulator\"\n label=\"Phone Simulator\"\n color=\"#10b981\"\n .hidden=${this.isVisible}\n @temba-button-clicked=${this.handleShow}\n ></temba-floating-tab>\n `;\n }\n}\n"]}
|
|
@@ -6,6 +6,26 @@ import { property } from 'lit/decorators.js';
|
|
|
6
6
|
import { produce } from 'immer';
|
|
7
7
|
export const FLOW_SPEC_VERSION = '14.3';
|
|
8
8
|
const CANVAS_PADDING = 800;
|
|
9
|
+
/**
|
|
10
|
+
* Sorts nodes by their position - first by y (top), then by x (left)
|
|
11
|
+
*/
|
|
12
|
+
function sortNodesByPosition(nodes, nodePositions) {
|
|
13
|
+
nodes.sort((a, b) => {
|
|
14
|
+
var _a, _b;
|
|
15
|
+
const posA = (_a = nodePositions[a.uuid]) === null || _a === void 0 ? void 0 : _a.position;
|
|
16
|
+
const posB = (_b = nodePositions[b.uuid]) === null || _b === void 0 ? void 0 : _b.position;
|
|
17
|
+
// if either position is missing, maintain current order
|
|
18
|
+
if (!posA || !posB) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
// sort by y (top) first
|
|
22
|
+
if (posA.top !== posB.top) {
|
|
23
|
+
return posA.top - posB.top;
|
|
24
|
+
}
|
|
25
|
+
// if y is same, sort by x (left)
|
|
26
|
+
return posA.left - posB.left;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
9
29
|
export const zustand = createStore()(subscribeWithSelector(immer((set, get) => ({
|
|
10
30
|
languageNames: {},
|
|
11
31
|
canvasSize: { width: 0, height: 0 },
|
|
@@ -15,6 +35,10 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
15
35
|
flowInfo: null,
|
|
16
36
|
isTranslating: false,
|
|
17
37
|
dirtyDate: null,
|
|
38
|
+
activity: null,
|
|
39
|
+
simulatorActivity: null,
|
|
40
|
+
activityEndpoint: null,
|
|
41
|
+
simulatorActive: false,
|
|
18
42
|
setDirtyDate: (date) => {
|
|
19
43
|
set((state) => {
|
|
20
44
|
state.dirtyDate = date;
|
|
@@ -48,6 +72,35 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
48
72
|
}, {});
|
|
49
73
|
set({ languageNames: allLanguages });
|
|
50
74
|
},
|
|
75
|
+
setActivityEndpoint: (endpoint) => {
|
|
76
|
+
set({ activityEndpoint: endpoint });
|
|
77
|
+
},
|
|
78
|
+
fetchActivity: async (endpoint) => {
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(endpoint);
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const data = await response.json();
|
|
85
|
+
set({ activity: data });
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('Failed to fetch activity:', error);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
updateActivity: (activity) => {
|
|
92
|
+
set({ activity });
|
|
93
|
+
},
|
|
94
|
+
updateSimulatorActivity: (activity) => {
|
|
95
|
+
set({ simulatorActivity: activity });
|
|
96
|
+
},
|
|
97
|
+
setSimulatorActive: (active) => {
|
|
98
|
+
set({ simulatorActive: active });
|
|
99
|
+
},
|
|
100
|
+
getCurrentActivity: () => {
|
|
101
|
+
const state = get();
|
|
102
|
+
return state.simulatorActive ? state.simulatorActivity : state.activity;
|
|
103
|
+
},
|
|
51
104
|
getFlowResults: () => {
|
|
52
105
|
const state = get();
|
|
53
106
|
return state.flowInfo.results;
|
|
@@ -66,12 +119,17 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
66
119
|
// todo: eventually we should be doing the fetching
|
|
67
120
|
setFlowContents: (flow) => {
|
|
68
121
|
set((state) => {
|
|
122
|
+
var _a, _b, _c;
|
|
69
123
|
const flowLang = flow.definition.language;
|
|
70
124
|
state.flowDefinition = flow.definition;
|
|
71
125
|
state.flowInfo = flow.info;
|
|
72
126
|
// Reset to the flow's default language when loading a new flow
|
|
73
127
|
state.languageCode = flowLang;
|
|
74
128
|
state.isTranslating = false;
|
|
129
|
+
// Sort nodes by position when loading flow
|
|
130
|
+
if (((_a = state.flowDefinition) === null || _a === void 0 ? void 0 : _a.nodes) && ((_c = (_b = state.flowDefinition) === null || _b === void 0 ? void 0 : _b._ui) === null || _c === void 0 ? void 0 : _c.nodes)) {
|
|
131
|
+
sortNodesByPosition(state.flowDefinition.nodes, state.flowDefinition._ui.nodes);
|
|
132
|
+
}
|
|
75
133
|
});
|
|
76
134
|
},
|
|
77
135
|
setFlowInfo: (info) => {
|
|
@@ -111,6 +169,8 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
111
169
|
positions[uuid];
|
|
112
170
|
}
|
|
113
171
|
}
|
|
172
|
+
// Sort nodes by position since positions may have changed
|
|
173
|
+
sortNodesByPosition(state.flowDefinition.nodes, state.flowDefinition._ui.nodes);
|
|
114
174
|
state.dirtyDate = new Date();
|
|
115
175
|
});
|
|
116
176
|
},
|
|
@@ -157,6 +217,8 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
157
217
|
}
|
|
158
218
|
});
|
|
159
219
|
});
|
|
220
|
+
// Sort nodes by position
|
|
221
|
+
sortNodesByPosition(draft.nodes, draft._ui.nodes);
|
|
160
222
|
});
|
|
161
223
|
state.dirtyDate = new Date();
|
|
162
224
|
});
|
|
@@ -267,6 +329,8 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
267
329
|
type: nodeType,
|
|
268
330
|
config: {}
|
|
269
331
|
};
|
|
332
|
+
// Sort nodes by position
|
|
333
|
+
sortNodesByPosition(state.flowDefinition.nodes, state.flowDefinition._ui.nodes);
|
|
270
334
|
state.dirtyDate = new Date();
|
|
271
335
|
});
|
|
272
336
|
return uuid;
|
|
@@ -280,6 +344,8 @@ export const zustand = createStore()(subscribeWithSelector(immer((set, get) => (
|
|
|
280
344
|
state.flowDefinition._ui.nodes = {};
|
|
281
345
|
}
|
|
282
346
|
state.flowDefinition._ui.nodes[node.uuid] = nodeUI;
|
|
347
|
+
// Sort nodes by position
|
|
348
|
+
sortNodesByPosition(state.flowDefinition.nodes, state.flowDefinition._ui.nodes);
|
|
283
349
|
state.dirtyDate = new Date();
|
|
284
350
|
});
|
|
285
351
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppState.js","sourceRoot":"","sources":["../../../src/store/AppState.ts"],"names":[],"mappings":"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","sourcesContent":["import { createStore, StoreApi } from 'zustand/vanilla';\nimport { fetchResults, generateUUID } from '../utils';\nimport {\n Action,\n Exit,\n FlowDefinition,\n FlowPosition,\n Node,\n NodeUI,\n Router,\n StickyNote\n} from './flow-definition';\nimport { immer } from 'zustand/middleware/immer';\nimport { subscribeWithSelector } from 'zustand/middleware';\nimport { property } from 'lit/decorators.js';\nimport { produce } from 'immer';\n\nexport const FLOW_SPEC_VERSION = '14.3';\nconst CANVAS_PADDING = 800;\n\nexport interface InfoResult {\n key: string;\n name: string;\n categories: string[];\n node_uuids: string[];\n}\n\nexport interface ObjectRef {\n uuid: string;\n name: string;\n}\n\nexport interface TypedObjectRef extends ObjectRef {\n type: string;\n}\n\nexport interface Language {\n code: string;\n name: string;\n}\n\nexport interface FlowInfo {\n results: InfoResult[];\n dependencies: TypedObjectRef[];\n counts: { nodes: number; languages: number };\n locals: string[];\n}\n\nexport interface FlowContents {\n definition: FlowDefinition;\n info: FlowInfo;\n}\n\nexport interface Workspace {\n anon: boolean;\n country: string;\n date_style: string;\n languages: string[];\n name: string;\n primary_language: string;\n timezone: string;\n uuid: string;\n}\n\nexport interface CanvasPositions {\n [uuid: string]: FlowPosition;\n}\n\nexport interface AppState {\n flowDefinition: FlowDefinition;\n flowInfo: FlowInfo;\n\n languageCode: string;\n languageNames: { [code: string]: Language };\n workspace: Workspace;\n isTranslating: boolean;\n\n dirtyDate: Date | null;\n\n canvasSize: { width: number; height: number };\n\n fetchRevision: (endpoint: string, id?: string) => void;\n fetchWorkspace: (endpoint: string) => Promise<void>;\n fetchAllLanguages: (endpoint: string) => Promise<void>;\n\n getFlowResults: () => InfoResult[];\n getResultByKey(id: any): InfoResult;\n\n setFlowContents: (flow: FlowContents) => void;\n setFlowInfo: (info: FlowInfo) => void;\n setRevision: (revision: number) => void;\n setLanguageCode: (languageCode: string) => void;\n setDirtyDate: (date: Date) => void;\n expandCanvas: (width: number, height: number) => void;\n\n updateNode(\n uuid: string,\n node: { actions: Action[]; uuid: string; exits: Exit[]; router?: Router }\n ): unknown;\n updateNodeUIConfig(uuid: string, config: Record<string, any>): unknown;\n updateConnection(\n nodeUuid: string,\n exitUuid: string,\n destinationNodeUuid: string\n ): unknown;\n updateCanvasPositions: (positions: CanvasPositions) => void;\n removeNodes: (uuids: string[]) => void;\n removeStickyNotes: (uuids: string[]) => void;\n updateStickyNote(uuid: string, sticky: StickyNote): void;\n createStickyNote(position: FlowPosition): string;\n createNode(nodeType: string, position: FlowPosition): string;\n addNode(node: Node, nodeUI: NodeUI): void;\n updateLocalization(\n languageCode: string,\n actionUuid: string,\n localizationData: Record<string, any>\n ): void;\n setTranslationFilters: (filters: { categories: boolean }) => void;\n markAutoTranslated: (\n languageCode: string,\n uuid: string,\n attributes: string[]\n ) => void;\n}\n\nexport const zustand = createStore<AppState>()(\n subscribeWithSelector(\n immer((set, get) => ({\n languageNames: {},\n canvasSize: { width: 0, height: 0 },\n languageCode: '',\n workspace: null,\n flowDefinition: null,\n flowInfo: null,\n isTranslating: false,\n dirtyDate: null,\n\n setDirtyDate: (date: Date) => {\n set((state: AppState) => {\n state.dirtyDate = date;\n });\n },\n\n fetchRevision: async (endpoint: string, id: string = null) => {\n if (!id) {\n id = 'latest';\n }\n const response = await fetch(\n `${endpoint}/${id}/?version=${FLOW_SPEC_VERSION}`\n );\n\n if (!response.ok) {\n throw new Error('Network response was not ok');\n }\n const data = (await response.json()) as FlowContents;\n set({ flowInfo: data.info, flowDefinition: data.definition });\n },\n\n fetchWorkspace: async (endpoint) => {\n const response = await fetch(endpoint);\n if (!response.ok) {\n throw new Error('Network response was not ok');\n }\n const data = await response.json();\n set({ workspace: data });\n },\n\n fetchAllLanguages: async (endpoint) => {\n const results = await fetchResults(endpoint);\n\n // convert array to map for easier lookup\n const allLanguages = results.reduce(function (\n languages: any,\n result: any\n ) {\n languages[result.value] = result.name;\n return languages;\n },\n {});\n\n set({ languageNames: allLanguages });\n },\n\n getFlowResults: () => {\n const state = get();\n return state.flowInfo.results;\n },\n\n getResultByKey: (id: any) => {\n const state = get();\n const results = state.flowInfo.results;\n return results.find((result) => result.key === id);\n },\n\n getLanguage: () => {\n const state = get();\n const languageCode = state.languageCode;\n const languageNames = state.languageNames;\n return { name: languageNames[languageCode], code: languageCode };\n },\n\n // todo: eventually we should be doing the fetching\n setFlowContents: (flow: FlowContents) => {\n set((state: AppState) => {\n const flowLang = flow.definition.language;\n state.flowDefinition = flow.definition;\n state.flowInfo = flow.info;\n // Reset to the flow's default language when loading a new flow\n state.languageCode = flowLang;\n state.isTranslating = false;\n });\n },\n\n setFlowInfo: (info: FlowInfo) => {\n set((state: AppState) => {\n state.flowInfo = info;\n });\n },\n\n setRevision: (revision: number) => {\n set((state: AppState) => {\n state.flowDefinition.revision = revision;\n });\n },\n\n setLanguageCode: (languageCode: string) => {\n set((state: AppState) => {\n state.languageCode = languageCode;\n state.isTranslating = state.flowDefinition.language !== languageCode;\n });\n },\n\n expandCanvas: (width: number, height: number) => {\n set((state: AppState) => {\n const minWidth = Math.max(\n state.canvasSize.width,\n width + CANVAS_PADDING\n );\n const minHeight = Math.max(\n state.canvasSize.height,\n height + CANVAS_PADDING\n );\n\n state.canvasSize.width = minWidth;\n state.canvasSize.height = minHeight;\n });\n },\n\n updateCanvasPositions: (positions: CanvasPositions) => {\n set((state: AppState) => {\n for (const uuid in positions) {\n // todo: add nodes that are created and then moved, for now ignore\n if (state.flowDefinition._ui.nodes[uuid]) {\n state.flowDefinition._ui.nodes[uuid].position = positions[uuid];\n }\n\n // otherwise, it might be a sticky\n else if (state.flowDefinition._ui.stickies[uuid]) {\n state.flowDefinition._ui.stickies[uuid].position =\n positions[uuid];\n }\n }\n state.dirtyDate = new Date();\n });\n },\n\n removeNodes: (uuids: string[]) => {\n set((state: AppState) => {\n for (const uuid of uuids) {\n delete state.flowDefinition._ui.nodes[uuid];\n }\n\n state.flowDefinition = produce(state.flowDefinition, (draft) => {\n // For each node being removed, check if we should reroute connections\n uuids.forEach((removedUuid) => {\n const removedNode = draft.nodes.find(\n (n) => n.uuid === removedUuid\n );\n\n if (!removedNode || !removedNode.exits.length) return;\n\n // Get all destinations (filter out null/undefined)\n const destinations = removedNode.exits\n .map((exit) => exit.destination_uuid)\n .filter((dest) => dest);\n\n // Only proceed if all exits have destinations and they all point to the same place\n if (\n destinations.length === removedNode.exits.length &&\n destinations.every((dest) => dest === destinations[0])\n ) {\n const targetDestination = destinations[0];\n // Don't reroute if the target is also being removed\n if (uuids.includes(targetDestination)) return;\n\n // Find all nodes with exits pointing to the node being removed\n draft.nodes.forEach((node) => {\n node.exits.forEach((exit) => {\n if (exit.destination_uuid === removedUuid) {\n // Reroute to the same destination the removed node was going to\n exit.destination_uuid = targetDestination;\n }\n });\n });\n }\n });\n\n // Remove the nodes\n draft.nodes = draft.nodes.filter(\n (node) => !uuids.includes(node.uuid)\n );\n\n // Clear any remaining connections to removed nodes that weren't rerouted\n draft.nodes.forEach((node) => {\n node.exits.forEach((exit) => {\n if (uuids.includes(exit.destination_uuid)) {\n exit.destination_uuid = null;\n }\n });\n });\n });\n\n state.dirtyDate = new Date();\n });\n },\n\n removeStickyNotes: (uuids: string[]) => {\n set((state: AppState) => {\n if (state.flowDefinition._ui?.stickies) {\n for (const uuid of uuids) {\n delete state.flowDefinition._ui.stickies[uuid];\n }\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateNode: (uuid: string, newNode: Node) => {\n set((state: AppState) => {\n const node = state.flowDefinition?.nodes.find((n) => n.uuid === uuid);\n if (node) {\n node.actions = newNode.actions;\n node.uuid = newNode.uuid;\n node.exits = newNode.exits;\n node.router = newNode.router;\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateNodeUIConfig: (uuid: string, config: Record<string, any>) => {\n set((state: AppState) => {\n if (state.flowDefinition._ui.nodes[uuid]) {\n // Handle type separately if provided\n if (config.type !== undefined) {\n state.flowDefinition._ui.nodes[uuid].type = config.type;\n }\n\n // Update config (excluding type)\n if (!state.flowDefinition._ui.nodes[uuid].config) {\n state.flowDefinition._ui.nodes[uuid].config = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type, ...configWithoutType } = config;\n Object.assign(\n state.flowDefinition._ui.nodes[uuid].config,\n configWithoutType\n );\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateConnection: (\n nodeUuid: string,\n exitUuid: string,\n destinationNodeUuid: string\n ) => {\n set((state: AppState) => {\n // Find the exit with this UUID\n const node = state.flowDefinition.nodes.find(\n (node) => node.uuid === nodeUuid\n );\n\n const exit = node?.exits.find((e) => e.uuid === exitUuid);\n if (exit) {\n // Update the destination\n exit.destination_uuid = destinationNodeUuid;\n state.dirtyDate = new Date();\n }\n });\n },\n\n updateStickyNote: (uuid: string, sticky: StickyNote) => {\n set((state: AppState) => {\n if (!state.flowDefinition._ui.stickies) {\n state.flowDefinition._ui.stickies = {};\n }\n state.flowDefinition._ui.stickies[uuid] = sticky;\n state.dirtyDate = new Date();\n });\n },\n\n createStickyNote: (position: FlowPosition): string => {\n const uuid = generateUUID();\n set((state: AppState) => {\n if (!state.flowDefinition._ui.stickies) {\n state.flowDefinition._ui.stickies = {};\n }\n\n const newSticky: StickyNote = {\n position,\n title: '',\n body: '',\n color: 'yellow'\n };\n\n state.flowDefinition._ui.stickies[uuid] = newSticky;\n state.dirtyDate = new Date();\n });\n return uuid;\n },\n\n createNode: (nodeType: string, position: FlowPosition): string => {\n const uuid = generateUUID();\n const exitUuid = generateUUID();\n\n set((state: AppState) => {\n // Create a basic node with a single exit\n const newNode: Node = {\n uuid,\n actions: [],\n exits: [\n {\n uuid: exitUuid,\n destination_uuid: null\n }\n ]\n };\n\n // Add the node to the flow definition\n state.flowDefinition.nodes.push(newNode);\n\n // Set up UI for the node\n if (!state.flowDefinition._ui.nodes) {\n state.flowDefinition._ui.nodes = {};\n }\n\n state.flowDefinition._ui.nodes[uuid] = {\n position,\n type: nodeType as any,\n config: {}\n };\n\n state.dirtyDate = new Date();\n });\n\n return uuid;\n },\n\n addNode: (node: Node, nodeUI: NodeUI) => {\n set((state: AppState) => {\n // Add the node to the flow definition\n state.flowDefinition.nodes.push(node);\n\n // Set up UI for the node\n if (!state.flowDefinition._ui.nodes) {\n state.flowDefinition._ui.nodes = {};\n }\n\n state.flowDefinition._ui.nodes[node.uuid] = nodeUI;\n\n state.dirtyDate = new Date();\n });\n },\n\n updateLocalization: (\n languageCode: string,\n actionUuid: string,\n localizationData: Record<string, any>\n ) => {\n set((state: AppState) => {\n // Initialize localization structure if it doesn't exist\n if (!state.flowDefinition.localization) {\n state.flowDefinition.localization = {};\n }\n\n if (!state.flowDefinition.localization[languageCode]) {\n state.flowDefinition.localization[languageCode] = {};\n }\n\n // Update or remove the localization for this action\n if (Object.keys(localizationData).length > 0) {\n state.flowDefinition.localization[languageCode][actionUuid] =\n localizationData;\n } else {\n // If no localized values, remove the entry\n delete state.flowDefinition.localization[languageCode][actionUuid];\n }\n\n // Clean up empty language sections\n if (\n Object.keys(state.flowDefinition.localization[languageCode])\n .length === 0\n ) {\n delete state.flowDefinition.localization[languageCode];\n }\n\n // Clean up empty localization object\n if (Object.keys(state.flowDefinition.localization).length === 0) {\n delete state.flowDefinition.localization;\n }\n\n state.dirtyDate = new Date();\n });\n },\n\n setTranslationFilters: (filters: { categories: boolean }) => {\n set((state: AppState) => {\n if (!state.flowDefinition?._ui) {\n return;\n }\n\n const currentFilters = state.flowDefinition._ui\n .translation_filters || {\n categories: false\n };\n\n state.flowDefinition._ui.translation_filters = {\n ...currentFilters,\n categories: !!filters.categories\n };\n\n state.dirtyDate = new Date();\n });\n },\n\n markAutoTranslated: (\n languageCode: string,\n uuid: string,\n attributes: string[]\n ) => {\n set((state: AppState) => {\n if (!state.flowDefinition?._ui) {\n return;\n }\n\n if (!state.flowDefinition._ui.auto_translations) {\n state.flowDefinition._ui.auto_translations = {};\n }\n\n if (!state.flowDefinition._ui.auto_translations[languageCode]) {\n state.flowDefinition._ui.auto_translations[languageCode] = {};\n }\n\n const existing =\n state.flowDefinition._ui.auto_translations[languageCode][uuid] ||\n [];\n\n const merged = Array.from(\n new Set([...existing, ...(attributes || [])])\n );\n\n state.flowDefinition._ui.auto_translations[languageCode][uuid] =\n merged;\n state.dirtyDate = new Date();\n });\n }\n }))\n )\n);\n\ntype SelectorAwareStoreApi<S extends object> = StoreApi<S> & {\n subscribe: <U>(\n selector: (state: S) => U,\n listener: (value: U, previous: U) => void\n ) => () => void;\n};\n\n/**\n * Custom Lit property decorator that binds a property to a Zustand store subscription.\n *\n * @param store - The Zustand store to subscribe to.\n * @param selector - A function selecting the slice of state to bind to the property.\n */\nexport function fromStore<S extends object, V = unknown>(\n store: SelectorAwareStoreApi<S>,\n selector: (state: S) => V\n): PropertyDecorator {\n return (proto: any, name: string | symbol) => {\n property()(proto, name as string);\n\n const connectedKey = 'connectedCallback';\n const disconnectedKey = 'disconnectedCallback';\n\n const userConnected = proto[connectedKey];\n const userDisconnected = proto[disconnectedKey];\n\n proto[connectedKey] = function () {\n this._zustandUnsubscribe ??= {};\n this[name] = selector(store.getState());\n\n this._zustandUnsubscribe[name] = store.subscribe(selector, (val: V) => {\n this[name] = val;\n });\n\n if (userConnected) userConnected.call(this);\n };\n\n proto[disconnectedKey] = function () {\n this._zustandUnsubscribe?.[name]?.();\n if (userDisconnected) userDisconnected.call(this);\n };\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AppState.js","sourceRoot":"","sources":["../../../src/store/AppState.ts"],"names":[],"mappings":"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","sourcesContent":["import { createStore, StoreApi } from 'zustand/vanilla';\nimport { fetchResults, generateUUID } from '../utils';\nimport {\n Action,\n Exit,\n FlowDefinition,\n FlowPosition,\n Node,\n NodeUI,\n Router,\n StickyNote\n} from './flow-definition';\nimport { immer } from 'zustand/middleware/immer';\nimport { subscribeWithSelector } from 'zustand/middleware';\nimport { property } from 'lit/decorators.js';\nimport { produce } from 'immer';\n\nexport const FLOW_SPEC_VERSION = '14.3';\nconst CANVAS_PADDING = 800;\n\n/**\n * Sorts nodes by their position - first by y (top), then by x (left)\n */\nfunction sortNodesByPosition(\n nodes: Node[],\n nodePositions: Record<string, NodeUI>\n): void {\n nodes.sort((a, b) => {\n const posA = nodePositions[a.uuid]?.position;\n const posB = nodePositions[b.uuid]?.position;\n\n // if either position is missing, maintain current order\n if (!posA || !posB) {\n return 0;\n }\n\n // sort by y (top) first\n if (posA.top !== posB.top) {\n return posA.top - posB.top;\n }\n\n // if y is same, sort by x (left)\n return posA.left - posB.left;\n });\n}\n\nexport interface InfoResult {\n key: string;\n name: string;\n categories: string[];\n node_uuids: string[];\n}\n\nexport interface ObjectRef {\n uuid: string;\n name: string;\n}\n\nexport interface TypedObjectRef extends ObjectRef {\n type: string;\n}\n\nexport interface Language {\n code: string;\n name: string;\n}\n\nexport interface FlowInfo {\n results: InfoResult[];\n dependencies: TypedObjectRef[];\n counts: { nodes: number; languages: number };\n locals: string[];\n}\n\nexport interface FlowContents {\n definition: FlowDefinition;\n info: FlowInfo;\n}\n\nexport interface Workspace {\n anon: boolean;\n country: string;\n date_style: string;\n languages: string[];\n name: string;\n primary_language: string;\n timezone: string;\n uuid: string;\n}\n\nexport interface CanvasPositions {\n [uuid: string]: FlowPosition;\n}\n\nexport interface Activity {\n segments: { [exitToDestinationKey: string]: number };\n nodes: { [nodeUuid: string]: number };\n}\n\nexport interface AppState {\n flowDefinition: FlowDefinition;\n flowInfo: FlowInfo;\n\n languageCode: string;\n languageNames: { [code: string]: Language };\n workspace: Workspace;\n isTranslating: boolean;\n\n dirtyDate: Date | null;\n\n canvasSize: { width: number; height: number };\n activity: Activity | null;\n simulatorActivity: Activity | null;\n activityEndpoint: string | null;\n simulatorActive: boolean;\n\n getCurrentActivity: () => Activity | null;\n fetchRevision: (endpoint: string, id?: string) => void;\n fetchWorkspace: (endpoint: string) => Promise<void>;\n fetchAllLanguages: (endpoint: string) => Promise<void>;\n fetchActivity: (endpoint: string) => Promise<void>;\n setActivityEndpoint: (endpoint: string) => void;\n updateActivity: (activity: Activity) => void;\n updateSimulatorActivity: (activity: Activity) => void;\n setSimulatorActive: (active: boolean) => void;\n\n getFlowResults: () => InfoResult[];\n getResultByKey(id: any): InfoResult;\n\n setFlowContents: (flow: FlowContents) => void;\n setFlowInfo: (info: FlowInfo) => void;\n setRevision: (revision: number) => void;\n setLanguageCode: (languageCode: string) => void;\n setDirtyDate: (date: Date) => void;\n expandCanvas: (width: number, height: number) => void;\n\n updateNode(\n uuid: string,\n node: { actions: Action[]; uuid: string; exits: Exit[]; router?: Router }\n ): unknown;\n updateNodeUIConfig(uuid: string, config: Record<string, any>): unknown;\n updateConnection(\n nodeUuid: string,\n exitUuid: string,\n destinationNodeUuid: string\n ): unknown;\n updateCanvasPositions: (positions: CanvasPositions) => void;\n removeNodes: (uuids: string[]) => void;\n removeStickyNotes: (uuids: string[]) => void;\n updateStickyNote(uuid: string, sticky: StickyNote): void;\n createStickyNote(position: FlowPosition): string;\n createNode(nodeType: string, position: FlowPosition): string;\n addNode(node: Node, nodeUI: NodeUI): void;\n updateLocalization(\n languageCode: string,\n actionUuid: string,\n localizationData: Record<string, any>\n ): void;\n setTranslationFilters: (filters: { categories: boolean }) => void;\n markAutoTranslated: (\n languageCode: string,\n uuid: string,\n attributes: string[]\n ) => void;\n}\n\nexport const zustand = createStore<AppState>()(\n subscribeWithSelector(\n immer((set, get) => ({\n languageNames: {},\n canvasSize: { width: 0, height: 0 },\n languageCode: '',\n workspace: null,\n flowDefinition: null,\n flowInfo: null,\n isTranslating: false,\n dirtyDate: null,\n activity: null,\n simulatorActivity: null,\n activityEndpoint: null,\n simulatorActive: false,\n\n setDirtyDate: (date: Date) => {\n set((state: AppState) => {\n state.dirtyDate = date;\n });\n },\n\n fetchRevision: async (endpoint: string, id: string = null) => {\n if (!id) {\n id = 'latest';\n }\n const response = await fetch(\n `${endpoint}/${id}/?version=${FLOW_SPEC_VERSION}`\n );\n\n if (!response.ok) {\n throw new Error('Network response was not ok');\n }\n const data = (await response.json()) as FlowContents;\n set({ flowInfo: data.info, flowDefinition: data.definition });\n },\n\n fetchWorkspace: async (endpoint) => {\n const response = await fetch(endpoint);\n if (!response.ok) {\n throw new Error('Network response was not ok');\n }\n const data = await response.json();\n set({ workspace: data });\n },\n\n fetchAllLanguages: async (endpoint) => {\n const results = await fetchResults(endpoint);\n\n // convert array to map for easier lookup\n const allLanguages = results.reduce(function (\n languages: any,\n result: any\n ) {\n languages[result.value] = result.name;\n return languages;\n },\n {});\n\n set({ languageNames: allLanguages });\n },\n\n setActivityEndpoint: (endpoint: string) => {\n set({ activityEndpoint: endpoint });\n },\n\n fetchActivity: async (endpoint: string) => {\n try {\n const response = await fetch(endpoint);\n if (!response.ok) {\n return;\n }\n const data = await response.json();\n set({ activity: data });\n } catch (error) {\n console.error('Failed to fetch activity:', error);\n }\n },\n\n updateActivity: (activity: Activity) => {\n set({ activity });\n },\n\n updateSimulatorActivity: (activity: Activity) => {\n set({ simulatorActivity: activity });\n },\n\n setSimulatorActive: (active: boolean) => {\n set({ simulatorActive: active });\n },\n\n getCurrentActivity: () => {\n const state = get();\n return state.simulatorActive ? state.simulatorActivity : state.activity;\n },\n\n getFlowResults: () => {\n const state = get();\n return state.flowInfo.results;\n },\n\n getResultByKey: (id: any) => {\n const state = get();\n const results = state.flowInfo.results;\n return results.find((result) => result.key === id);\n },\n\n getLanguage: () => {\n const state = get();\n const languageCode = state.languageCode;\n const languageNames = state.languageNames;\n return { name: languageNames[languageCode], code: languageCode };\n },\n\n // todo: eventually we should be doing the fetching\n setFlowContents: (flow: FlowContents) => {\n set((state: AppState) => {\n const flowLang = flow.definition.language;\n state.flowDefinition = flow.definition;\n state.flowInfo = flow.info;\n // Reset to the flow's default language when loading a new flow\n state.languageCode = flowLang;\n state.isTranslating = false;\n\n // Sort nodes by position when loading flow\n if (state.flowDefinition?.nodes && state.flowDefinition?._ui?.nodes) {\n sortNodesByPosition(\n state.flowDefinition.nodes,\n state.flowDefinition._ui.nodes\n );\n }\n });\n },\n\n setFlowInfo: (info: FlowInfo) => {\n set((state: AppState) => {\n state.flowInfo = info;\n });\n },\n\n setRevision: (revision: number) => {\n set((state: AppState) => {\n state.flowDefinition.revision = revision;\n });\n },\n\n setLanguageCode: (languageCode: string) => {\n set((state: AppState) => {\n state.languageCode = languageCode;\n state.isTranslating = state.flowDefinition.language !== languageCode;\n });\n },\n\n expandCanvas: (width: number, height: number) => {\n set((state: AppState) => {\n const minWidth = Math.max(\n state.canvasSize.width,\n width + CANVAS_PADDING\n );\n const minHeight = Math.max(\n state.canvasSize.height,\n height + CANVAS_PADDING\n );\n\n state.canvasSize.width = minWidth;\n state.canvasSize.height = minHeight;\n });\n },\n\n updateCanvasPositions: (positions: CanvasPositions) => {\n set((state: AppState) => {\n for (const uuid in positions) {\n // todo: add nodes that are created and then moved, for now ignore\n if (state.flowDefinition._ui.nodes[uuid]) {\n state.flowDefinition._ui.nodes[uuid].position = positions[uuid];\n }\n\n // otherwise, it might be a sticky\n else if (state.flowDefinition._ui.stickies[uuid]) {\n state.flowDefinition._ui.stickies[uuid].position =\n positions[uuid];\n }\n }\n\n // Sort nodes by position since positions may have changed\n sortNodesByPosition(\n state.flowDefinition.nodes,\n state.flowDefinition._ui.nodes\n );\n\n state.dirtyDate = new Date();\n });\n },\n\n removeNodes: (uuids: string[]) => {\n set((state: AppState) => {\n for (const uuid of uuids) {\n delete state.flowDefinition._ui.nodes[uuid];\n }\n\n state.flowDefinition = produce(state.flowDefinition, (draft) => {\n // For each node being removed, check if we should reroute connections\n uuids.forEach((removedUuid) => {\n const removedNode = draft.nodes.find(\n (n) => n.uuid === removedUuid\n );\n\n if (!removedNode || !removedNode.exits.length) return;\n\n // Get all destinations (filter out null/undefined)\n const destinations = removedNode.exits\n .map((exit) => exit.destination_uuid)\n .filter((dest) => dest);\n\n // Only proceed if all exits have destinations and they all point to the same place\n if (\n destinations.length === removedNode.exits.length &&\n destinations.every((dest) => dest === destinations[0])\n ) {\n const targetDestination = destinations[0];\n // Don't reroute if the target is also being removed\n if (uuids.includes(targetDestination)) return;\n\n // Find all nodes with exits pointing to the node being removed\n draft.nodes.forEach((node) => {\n node.exits.forEach((exit) => {\n if (exit.destination_uuid === removedUuid) {\n // Reroute to the same destination the removed node was going to\n exit.destination_uuid = targetDestination;\n }\n });\n });\n }\n });\n\n // Remove the nodes\n draft.nodes = draft.nodes.filter(\n (node) => !uuids.includes(node.uuid)\n );\n\n // Clear any remaining connections to removed nodes that weren't rerouted\n draft.nodes.forEach((node) => {\n node.exits.forEach((exit) => {\n if (uuids.includes(exit.destination_uuid)) {\n exit.destination_uuid = null;\n }\n });\n });\n\n // Sort nodes by position\n sortNodesByPosition(draft.nodes, draft._ui.nodes);\n });\n\n state.dirtyDate = new Date();\n });\n },\n\n removeStickyNotes: (uuids: string[]) => {\n set((state: AppState) => {\n if (state.flowDefinition._ui?.stickies) {\n for (const uuid of uuids) {\n delete state.flowDefinition._ui.stickies[uuid];\n }\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateNode: (uuid: string, newNode: Node) => {\n set((state: AppState) => {\n const node = state.flowDefinition?.nodes.find((n) => n.uuid === uuid);\n if (node) {\n node.actions = newNode.actions;\n node.uuid = newNode.uuid;\n node.exits = newNode.exits;\n node.router = newNode.router;\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateNodeUIConfig: (uuid: string, config: Record<string, any>) => {\n set((state: AppState) => {\n if (state.flowDefinition._ui.nodes[uuid]) {\n // Handle type separately if provided\n if (config.type !== undefined) {\n state.flowDefinition._ui.nodes[uuid].type = config.type;\n }\n\n // Update config (excluding type)\n if (!state.flowDefinition._ui.nodes[uuid].config) {\n state.flowDefinition._ui.nodes[uuid].config = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type, ...configWithoutType } = config;\n Object.assign(\n state.flowDefinition._ui.nodes[uuid].config,\n configWithoutType\n );\n }\n state.dirtyDate = new Date();\n });\n },\n\n updateConnection: (\n nodeUuid: string,\n exitUuid: string,\n destinationNodeUuid: string\n ) => {\n set((state: AppState) => {\n // Find the exit with this UUID\n const node = state.flowDefinition.nodes.find(\n (node) => node.uuid === nodeUuid\n );\n\n const exit = node?.exits.find((e) => e.uuid === exitUuid);\n if (exit) {\n // Update the destination\n exit.destination_uuid = destinationNodeUuid;\n state.dirtyDate = new Date();\n }\n });\n },\n\n updateStickyNote: (uuid: string, sticky: StickyNote) => {\n set((state: AppState) => {\n if (!state.flowDefinition._ui.stickies) {\n state.flowDefinition._ui.stickies = {};\n }\n state.flowDefinition._ui.stickies[uuid] = sticky;\n state.dirtyDate = new Date();\n });\n },\n\n createStickyNote: (position: FlowPosition): string => {\n const uuid = generateUUID();\n set((state: AppState) => {\n if (!state.flowDefinition._ui.stickies) {\n state.flowDefinition._ui.stickies = {};\n }\n\n const newSticky: StickyNote = {\n position,\n title: '',\n body: '',\n color: 'yellow'\n };\n\n state.flowDefinition._ui.stickies[uuid] = newSticky;\n state.dirtyDate = new Date();\n });\n return uuid;\n },\n\n createNode: (nodeType: string, position: FlowPosition): string => {\n const uuid = generateUUID();\n const exitUuid = generateUUID();\n\n set((state: AppState) => {\n // Create a basic node with a single exit\n const newNode: Node = {\n uuid,\n actions: [],\n exits: [\n {\n uuid: exitUuid,\n destination_uuid: null\n }\n ]\n };\n\n // Add the node to the flow definition\n state.flowDefinition.nodes.push(newNode);\n\n // Set up UI for the node\n if (!state.flowDefinition._ui.nodes) {\n state.flowDefinition._ui.nodes = {};\n }\n\n state.flowDefinition._ui.nodes[uuid] = {\n position,\n type: nodeType as any,\n config: {}\n };\n\n // Sort nodes by position\n sortNodesByPosition(\n state.flowDefinition.nodes,\n state.flowDefinition._ui.nodes\n );\n\n state.dirtyDate = new Date();\n });\n\n return uuid;\n },\n\n addNode: (node: Node, nodeUI: NodeUI) => {\n set((state: AppState) => {\n // Add the node to the flow definition\n state.flowDefinition.nodes.push(node);\n\n // Set up UI for the node\n if (!state.flowDefinition._ui.nodes) {\n state.flowDefinition._ui.nodes = {};\n }\n\n state.flowDefinition._ui.nodes[node.uuid] = nodeUI;\n\n // Sort nodes by position\n sortNodesByPosition(\n state.flowDefinition.nodes,\n state.flowDefinition._ui.nodes\n );\n\n state.dirtyDate = new Date();\n });\n },\n\n updateLocalization: (\n languageCode: string,\n actionUuid: string,\n localizationData: Record<string, any>\n ) => {\n set((state: AppState) => {\n // Initialize localization structure if it doesn't exist\n if (!state.flowDefinition.localization) {\n state.flowDefinition.localization = {};\n }\n\n if (!state.flowDefinition.localization[languageCode]) {\n state.flowDefinition.localization[languageCode] = {};\n }\n\n // Update or remove the localization for this action\n if (Object.keys(localizationData).length > 0) {\n state.flowDefinition.localization[languageCode][actionUuid] =\n localizationData;\n } else {\n // If no localized values, remove the entry\n delete state.flowDefinition.localization[languageCode][actionUuid];\n }\n\n // Clean up empty language sections\n if (\n Object.keys(state.flowDefinition.localization[languageCode])\n .length === 0\n ) {\n delete state.flowDefinition.localization[languageCode];\n }\n\n // Clean up empty localization object\n if (Object.keys(state.flowDefinition.localization).length === 0) {\n delete state.flowDefinition.localization;\n }\n\n state.dirtyDate = new Date();\n });\n },\n\n setTranslationFilters: (filters: { categories: boolean }) => {\n set((state: AppState) => {\n if (!state.flowDefinition?._ui) {\n return;\n }\n\n const currentFilters = state.flowDefinition._ui\n .translation_filters || {\n categories: false\n };\n\n state.flowDefinition._ui.translation_filters = {\n ...currentFilters,\n categories: !!filters.categories\n };\n\n state.dirtyDate = new Date();\n });\n },\n\n markAutoTranslated: (\n languageCode: string,\n uuid: string,\n attributes: string[]\n ) => {\n set((state: AppState) => {\n if (!state.flowDefinition?._ui) {\n return;\n }\n\n if (!state.flowDefinition._ui.auto_translations) {\n state.flowDefinition._ui.auto_translations = {};\n }\n\n if (!state.flowDefinition._ui.auto_translations[languageCode]) {\n state.flowDefinition._ui.auto_translations[languageCode] = {};\n }\n\n const existing =\n state.flowDefinition._ui.auto_translations[languageCode][uuid] ||\n [];\n\n const merged = Array.from(\n new Set([...existing, ...(attributes || [])])\n );\n\n state.flowDefinition._ui.auto_translations[languageCode][uuid] =\n merged;\n state.dirtyDate = new Date();\n });\n }\n }))\n )\n);\n\ntype SelectorAwareStoreApi<S extends object> = StoreApi<S> & {\n subscribe: <U>(\n selector: (state: S) => U,\n listener: (value: U, previous: U) => void\n ) => () => void;\n};\n\n/**\n * Custom Lit property decorator that binds a property to a Zustand store subscription.\n *\n * @param store - The Zustand store to subscribe to.\n * @param selector - A function selecting the slice of state to bind to the property.\n */\nexport function fromStore<S extends object, V = unknown>(\n store: SelectorAwareStoreApi<S>,\n selector: (state: S) => V\n): PropertyDecorator {\n return (proto: any, name: string | symbol) => {\n property()(proto, name as string);\n\n const connectedKey = 'connectedCallback';\n const disconnectedKey = 'disconnectedCallback';\n\n const userConnected = proto[connectedKey];\n const userDisconnected = proto[disconnectedKey];\n\n proto[connectedKey] = function () {\n this._zustandUnsubscribe ??= {};\n this[name] = selector(store.getState());\n\n this._zustandUnsubscribe[name] = store.subscribe(selector, (val: V) => {\n this[name] = val;\n });\n\n if (userConnected) userConnected.call(this);\n };\n\n proto[disconnectedKey] = function () {\n this._zustandUnsubscribe?.[name]?.();\n if (userDisconnected) userDisconnected.call(this);\n };\n };\n}\n"]}
|
package/out-tsc/src/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
2
2
|
import { html } from 'lit-html';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
3
4
|
import ColorHash from 'color-hash';
|
|
4
5
|
import { v4 as generateUUID, v7 as generateUUIDv7 } from 'uuid';
|
|
5
6
|
export const DEFAULT_MEDIA_ENDPOINT = '/api/v2/media.json';
|
|
@@ -529,6 +530,53 @@ export const getCookie = (name) => {
|
|
|
529
530
|
export const getCookieBoolean = (name) => {
|
|
530
531
|
return (getCookie(name) || '') === 'true';
|
|
531
532
|
};
|
|
533
|
+
/**
|
|
534
|
+
* Custom Lit property decorator that binds a property to a cookie.
|
|
535
|
+
* The property value is loaded from the cookie on component connection
|
|
536
|
+
* and automatically saved to the cookie whenever it changes.
|
|
537
|
+
*
|
|
538
|
+
* @param cookieName - The name of the cookie to use for storage.
|
|
539
|
+
* @param defaultValue - Optional default value if cookie doesn't exist.
|
|
540
|
+
*/
|
|
541
|
+
export function fromCookie(cookieName, defaultValue) {
|
|
542
|
+
return (proto, propertyName) => {
|
|
543
|
+
// register as a reactive property
|
|
544
|
+
property()(proto, propertyName);
|
|
545
|
+
const connectedKey = 'connectedCallback';
|
|
546
|
+
const updatedKey = 'updated';
|
|
547
|
+
const userConnected = proto[connectedKey];
|
|
548
|
+
const userUpdated = proto[updatedKey];
|
|
549
|
+
// on connect, load value from cookie
|
|
550
|
+
proto[connectedKey] = function () {
|
|
551
|
+
const cookieValue = getCookie(cookieName);
|
|
552
|
+
if (cookieValue !== null) {
|
|
553
|
+
// parse boolean values
|
|
554
|
+
if (cookieValue === 'true') {
|
|
555
|
+
this[propertyName] = true;
|
|
556
|
+
}
|
|
557
|
+
else if (cookieValue === 'false') {
|
|
558
|
+
this[propertyName] = false;
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
this[propertyName] = cookieValue;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
else if (defaultValue !== undefined) {
|
|
565
|
+
this[propertyName] = defaultValue;
|
|
566
|
+
}
|
|
567
|
+
if (userConnected)
|
|
568
|
+
userConnected.call(this);
|
|
569
|
+
};
|
|
570
|
+
// on property change, save to cookie
|
|
571
|
+
proto[updatedKey] = function (changedProperties) {
|
|
572
|
+
if (changedProperties.has(propertyName)) {
|
|
573
|
+
setCookie(cookieName, this[propertyName]);
|
|
574
|
+
}
|
|
575
|
+
if (userUpdated)
|
|
576
|
+
userUpdated.call(this, changedProperties);
|
|
577
|
+
};
|
|
578
|
+
};
|
|
579
|
+
}
|
|
532
580
|
export var COOKIE_KEYS;
|
|
533
581
|
(function (COOKIE_KEYS) {
|
|
534
582
|
COOKIE_KEYS["SETTINGS"] = "settings";
|