@nyaruka/temba-components 0.108.7 → 0.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/dist/static/svg/index.svg +1 -1
  3. package/dist/temba-components.js +602 -455
  4. package/dist/temba-components.js.map +1 -1
  5. package/out-tsc/src/charcount/CharCount.js +4 -5
  6. package/out-tsc/src/charcount/CharCount.js.map +1 -1
  7. package/out-tsc/src/completion/Completion.js +27 -16
  8. package/out-tsc/src/completion/Completion.js.map +1 -1
  9. package/out-tsc/src/compose/Compose.js +259 -95
  10. package/out-tsc/src/compose/Compose.js.map +1 -1
  11. package/out-tsc/src/contacts/ContactChat.js +18 -16
  12. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  13. package/out-tsc/src/contacts/ContactTickets.js +1 -1
  14. package/out-tsc/src/contacts/ContactTickets.js.map +1 -1
  15. package/out-tsc/src/interfaces.js.map +1 -1
  16. package/out-tsc/src/list/ShortcutList.js +125 -0
  17. package/out-tsc/src/list/ShortcutList.js.map +1 -0
  18. package/out-tsc/src/list/TembaList.js +8 -5
  19. package/out-tsc/src/list/TembaList.js.map +1 -1
  20. package/out-tsc/src/options/Options.js +46 -35
  21. package/out-tsc/src/options/Options.js.map +1 -1
  22. package/out-tsc/src/select/Select.js +1 -1
  23. package/out-tsc/src/select/Select.js.map +1 -1
  24. package/out-tsc/src/store/Store.js +18 -3
  25. package/out-tsc/src/store/Store.js.map +1 -1
  26. package/out-tsc/src/tabpane/Tab.js +2 -0
  27. package/out-tsc/src/tabpane/Tab.js.map +1 -1
  28. package/out-tsc/src/tabpane/TabPane.js +27 -5
  29. package/out-tsc/src/tabpane/TabPane.js.map +1 -1
  30. package/out-tsc/src/textinput/TextInput.js +7 -2
  31. package/out-tsc/src/textinput/TextInput.js.map +1 -1
  32. package/out-tsc/src/utils/index.js.map +1 -1
  33. package/out-tsc/src/vectoricon/index.js +2 -2
  34. package/out-tsc/src/vectoricon/index.js.map +1 -1
  35. package/out-tsc/temba-modules.js +2 -0
  36. package/out-tsc/temba-modules.js.map +1 -1
  37. package/out-tsc/test/temba-compose.test.js +26 -18
  38. package/out-tsc/test/temba-compose.test.js.map +1 -1
  39. package/out-tsc/test/temba-contact-chat.test.js +27 -18
  40. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  41. package/package.json +1 -1
  42. package/screenshots/truth/compose/attachments-and-send-button.png +0 -0
  43. package/screenshots/truth/compose/attachments-no-send-button.png +0 -0
  44. package/screenshots/truth/compose/attachments-with-all-files-and-click-send.png +0 -0
  45. package/screenshots/truth/compose/attachments-with-all-files.png +0 -0
  46. package/screenshots/truth/compose/attachments-with-failure-files.png +0 -0
  47. package/screenshots/truth/compose/attachments-with-success-files-and-click-send.png +0 -0
  48. package/screenshots/truth/compose/attachments-with-success-files.png +0 -0
  49. package/screenshots/truth/compose/chatbox-attachments-counter-and-send-button.png +0 -0
  50. package/screenshots/truth/compose/chatbox-attachments-counter-no-send-button.png +0 -0
  51. package/screenshots/truth/compose/chatbox-attachments-no-counter-and-send-button.png +0 -0
  52. package/screenshots/truth/compose/chatbox-attachments-no-counter-no-send-button.png +0 -0
  53. package/screenshots/truth/compose/chatbox-counter-and-send-button.png +0 -0
  54. package/screenshots/truth/compose/chatbox-counter-no-send-button.png +0 -0
  55. package/screenshots/truth/compose/chatbox-no-counter-and-send-button.png +0 -0
  56. package/screenshots/truth/compose/chatbox-no-counter-no-send-button.png +0 -0
  57. package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files-and-click-send.png +0 -0
  58. package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files.png +0 -0
  59. package/screenshots/truth/compose/chatbox-no-text-attachments-with-failure-files.png +0 -0
  60. package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files-and-click-send.png +0 -0
  61. package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files.png +0 -0
  62. package/screenshots/truth/compose/chatbox-with-text-and-click-send.png +0 -0
  63. package/screenshots/truth/compose/chatbox-with-text-and-hit-enter.png +0 -0
  64. package/screenshots/truth/compose/chatbox-with-text-and-spaces.png +0 -0
  65. package/screenshots/truth/compose/chatbox-with-text-and-url.png +0 -0
  66. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-click-send.png +0 -0
  67. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-hit-enter.png +0 -0
  68. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files.png +0 -0
  69. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-click-send.png +0 -0
  70. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-hit-enter.png +0 -0
  71. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files.png +0 -0
  72. package/screenshots/truth/compose/chatbox-with-text-attachments-with-failure-files.png +0 -0
  73. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-click-send.png +0 -0
  74. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-hit-enter.png +0 -0
  75. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files.png +0 -0
  76. package/screenshots/truth/compose/chatbox-with-text-no-spaces.png +0 -0
  77. package/screenshots/truth/compose/chatbox-with-text.png +0 -0
  78. package/screenshots/truth/contacts/compose-attachments-no-text-failure.png +0 -0
  79. package/screenshots/truth/contacts/compose-attachments-no-text-success.png +0 -0
  80. package/screenshots/truth/contacts/compose-text-and-attachments-failure-attachments.png +0 -0
  81. package/screenshots/truth/contacts/compose-text-and-attachments-failure-generic.png +0 -0
  82. package/screenshots/truth/contacts/compose-text-and-attachments-failure-text-and-attachments.png +0 -0
  83. package/screenshots/truth/contacts/compose-text-and-attachments-failure-text.png +0 -0
  84. package/screenshots/truth/contacts/compose-text-and-attachments-success.png +0 -0
  85. package/screenshots/truth/contacts/compose-text-no-attachments-failure.png +0 -0
  86. package/screenshots/truth/contacts/compose-text-no-attachments-success.png +0 -0
  87. package/screenshots/truth/contacts/contact-active-default.png +0 -0
  88. package/screenshots/truth/contacts/contact-active-show-chatbox.png +0 -0
  89. package/screenshots/truth/counter/summary.png +0 -0
  90. package/screenshots/truth/counter/text.png +0 -0
  91. package/screenshots/truth/counter/unicode-variables.png +0 -0
  92. package/screenshots/truth/counter/unicode.png +0 -0
  93. package/screenshots/truth/counter/variable.png +0 -0
  94. package/src/charcount/CharCount.ts +4 -5
  95. package/src/completion/Completion.ts +33 -19
  96. package/src/compose/Compose.ts +289 -96
  97. package/src/contacts/ContactChat.ts +18 -16
  98. package/src/contacts/ContactTickets.ts +1 -1
  99. package/src/interfaces.ts +7 -0
  100. package/src/list/ShortcutList.ts +137 -0
  101. package/src/list/TembaList.ts +9 -6
  102. package/src/options/Options.ts +53 -44
  103. package/src/select/Select.ts +1 -1
  104. package/src/store/Store.ts +23 -4
  105. package/src/tabpane/Tab.ts +2 -0
  106. package/src/tabpane/TabPane.ts +28 -5
  107. package/src/textinput/TextInput.ts +9 -3
  108. package/src/utils/index.ts +8 -2
  109. package/src/vectoricon/index.ts +2 -2
  110. package/static/svg/index.svg +1 -1
  111. package/static/svg/work/traced/zap-fast.svg +1 -0
  112. package/static/svg/work/used/zap-fast.svg +3 -0
  113. package/temba-modules.ts +2 -0
  114. package/test/temba-compose.test.ts +28 -35
  115. package/test/temba-contact-chat.test.ts +28 -37
  116. package/test-assets/store/shortcuts.json +14 -0
  117. package/static/svg/work/traced/message-dots-circle.svg +0 -1
  118. package/static/svg/work/used/message-dots-circle.svg +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,mCAAsB,CAAA;IACtB,uCAA0B,CAAA;IAC1B,qCAAwB,CAAA;AAC1B,CAAC,EAJW,SAAS,KAAT,SAAS,QAIpB;AAED,MAAM,CAAN,IAAY,kBAIX;AAJD,WAAY,kBAAkB;IAC5B,sDAAgC,CAAA;IAChC,gEAA0C,CAAA;IAC1C,4DAAsC,CAAA;AACxC,CAAC,EAJW,kBAAkB,KAAlB,kBAAkB,QAI7B;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACnB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AAoND,MAAM,CAAN,IAAY,eAwBX;AAxBD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,8CAA2B,CAAA;IAC3B,yDAAsC,CAAA;IACtC,gDAA6B,CAAA;IAC7B,gDAA6B,CAAA;IAC7B,yDAAsC,CAAA;IACtC,uDAAoC,CAAA;IACpC,6DAA0C,CAAA;IAC1C,2DAAwC,CAAA;IACxC,2DAAwC,CAAA;IACxC,yDAAsC,CAAA;IACtC,qDAAkC,CAAA;IAClC,gDAA6B,CAAA;IAC7B,kDAA+B,CAAA;IAC/B,2CAAwB,CAAA;IACxB,uDAAoC,CAAA;IACpC,wCAAqB,CAAA;IACrB,uDAAoC,CAAA;IACpC,iDAA8B,CAAA;IAC9B,+CAA4B,CAAA;IAC5B,4CAAyB,CAAA;IACzB,2DAAwC,CAAA;AAC1C,CAAC,EAxBW,eAAe,KAAf,eAAe,QAwB1B","sourcesContent":["export interface Workspace {\n uuid: string;\n name: string;\n country: string;\n languages: string[];\n timezone: string;\n date_style: DateStyle;\n anon: boolean;\n}\n\nexport interface Language {\n iso: string;\n name: string;\n}\n\nexport interface Attachment {\n uuid: string;\n content_type: string;\n url: string;\n filename: string;\n size: number;\n error: string;\n}\n\nexport enum DateStyle {\n DayFirst = 'day_first',\n MonthFirst = 'month_first',\n YearFirst = 'year_first'\n}\n\nexport enum ScheduledEventType {\n CampaignEvent = 'campaign_event',\n ScheduledBroadcast = 'scheduled_broadcast',\n ScheduledTrigger = 'scheduled_trigger'\n}\n\nexport enum TicketStatus {\n Open = 'open',\n Closed = 'closed'\n}\n\nexport interface ScheduledEvent {\n type: ScheduledEventType;\n scheduled: string;\n repeat_period: string;\n campaign?: ObjectReference;\n flow?: ObjectReference;\n message?: string;\n}\n\nexport interface NamedUser extends User {\n name: string;\n}\n\nexport interface User {\n id?: number;\n first_name?: string;\n last_name?: string;\n email?: string;\n role?: string;\n created_on?: string;\n avatar?: string;\n}\n\nexport interface Ticket {\n uuid: string;\n subject: string;\n body?: string;\n closed_on: string;\n opened_on: string;\n status: string;\n contact: ObjectReference;\n topic: ObjectReference;\n assignee?: { email: string; name: string; avatar?: string };\n}\n\nexport interface FlowResult {\n key: string;\n name: string;\n categories: string[];\n node_uuids: string[];\n}\n\nexport interface FlowDetails {\n name: string;\n results: FlowResult[];\n modified_on: string;\n runs: {\n active: number;\n completed: number;\n expired: number;\n interrupted: number;\n };\n}\n\nexport interface Msg {\n text: string;\n status: string;\n channel: ObjectReference;\n quick_replies: string[];\n urn: string;\n id: number;\n direction: string;\n type: string;\n attachments: string[];\n}\n\nexport interface ObjectReference {\n uuid: string;\n name: string;\n}\n\nexport interface ContactField {\n key: string;\n label: string;\n value_type: string;\n featured: boolean;\n priority: number;\n agent_access: string;\n type: string;\n usages: { campaign_events: number; flows: number; groups: number };\n}\n\nexport interface ContactGroup {\n uuid: string;\n count: number;\n name: string;\n query?: string;\n status: string;\n}\n\nexport interface URN {\n scheme: string;\n path: string;\n}\n\nexport interface Group {\n name: string;\n uuid: string;\n is_dynamic?: boolean;\n}\n\nexport interface ContactNote {\n text: string;\n created_on: string;\n created_by: NamedUser;\n}\n\nexport interface ContactTicket {\n name: string;\n uuid: string;\n status: string;\n\n contact: {\n uuid: string;\n name: string;\n created_on: Date;\n last_seen_on: Date;\n };\n}\n\nexport interface Contact {\n name: string;\n uuid: string;\n stopped: boolean;\n blocked: boolean;\n urns: string[];\n language?: string;\n fields: { [key: string]: string };\n groups: Group[];\n notes: ContactNote[];\n modified_on: string;\n created_on: string;\n last_seen_on: string;\n status: string;\n\n anon_display?: string;\n flow?: ObjectReference;\n last_msg?: Msg;\n direction?: string;\n ticket: {\n uuid: string;\n subject: string;\n closed_on?: string;\n last_activity_on: string;\n assignee?: User;\n topic?: ObjectReference;\n };\n}\n\nexport interface FeatureProperties {\n name: string;\n osm_id: string;\n level: number;\n children?: FeatureProperties[];\n has_children?: boolean;\n aliases?: string;\n parent_osm_id?: string;\n id?: number;\n path?: string;\n}\n\nexport interface Position {\n top: number;\n left: number;\n}\n\nexport interface FunctionExample {\n template: string;\n output: string;\n}\n\nexport interface CompletionOption {\n name?: string;\n summary: string;\n\n // functions\n signature?: string;\n detail?: string;\n examples?: FunctionExample[];\n}\n\nexport interface CompletionResult {\n anchorPosition: Position;\n query: string;\n options: CompletionOption[];\n currentFunction: CompletionOption;\n}\n\nexport interface CompletionProperty {\n key: string;\n help: string;\n type: string;\n}\n\nexport interface CompletionType {\n name: string;\n\n key_source?: string;\n property_template?: CompletionProperty;\n properties?: CompletionProperty[];\n}\n\nexport interface CompletionSchema {\n types: CompletionType[];\n root: CompletionProperty[];\n root_no_session: CompletionProperty[];\n}\n\nexport type KeyedAssets = { [assetType: string]: string[] };\n\nexport enum CustomEventType {\n Loaded = 'temba-loaded',\n Loading = 'temba-loading',\n Canceled = 'temba-canceled',\n CursorChanged = 'temba-cursor-changed',\n Refreshed = 'temba-refreshed',\n Selection = 'temba-selection',\n ButtonClicked = 'temba-button-clicked',\n DialogHidden = 'temba-dialog-hidden',\n ScrollThreshold = 'temba-scroll-threshold',\n ContentChanged = 'temba-content-changed',\n ContextChanged = 'temba-context-changed',\n FetchComplete = 'temba-fetch-complete',\n MessageSent = 'temba-message-sent',\n Submitted = 'temba-submitted',\n Redirected = 'temba-redirected',\n NoPath = 'temba-no-path',\n StoreUpdated = 'temba-store-updated',\n Ready = 'temba-ready',\n OrderChanged = 'temba-order-changed',\n DragStart = 'temba-drag-start',\n DragStop = 'temba-drag-stop',\n Resized = 'temba-resized',\n DetailsChanged = 'temba-details-changed'\n}\n"]}
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,mCAAsB,CAAA;IACtB,uCAA0B,CAAA;IAC1B,qCAAwB,CAAA;AAC1B,CAAC,EAJW,SAAS,KAAT,SAAS,QAIpB;AAED,MAAM,CAAN,IAAY,kBAIX;AAJD,WAAY,kBAAkB;IAC5B,sDAAgC,CAAA;IAChC,gEAA0C,CAAA;IAC1C,4DAAsC,CAAA;AACxC,CAAC,EAJW,kBAAkB,KAAlB,kBAAkB,QAI7B;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,iCAAiB,CAAA;AACnB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AA2ND,MAAM,CAAN,IAAY,eAwBX;AAxBD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,8CAA2B,CAAA;IAC3B,yDAAsC,CAAA;IACtC,gDAA6B,CAAA;IAC7B,gDAA6B,CAAA;IAC7B,yDAAsC,CAAA;IACtC,uDAAoC,CAAA;IACpC,6DAA0C,CAAA;IAC1C,2DAAwC,CAAA;IACxC,2DAAwC,CAAA;IACxC,yDAAsC,CAAA;IACtC,qDAAkC,CAAA;IAClC,gDAA6B,CAAA;IAC7B,kDAA+B,CAAA;IAC/B,2CAAwB,CAAA;IACxB,uDAAoC,CAAA;IACpC,wCAAqB,CAAA;IACrB,uDAAoC,CAAA;IACpC,iDAA8B,CAAA;IAC9B,+CAA4B,CAAA;IAC5B,4CAAyB,CAAA;IACzB,2DAAwC,CAAA;AAC1C,CAAC,EAxBW,eAAe,KAAf,eAAe,QAwB1B","sourcesContent":["export interface Workspace {\n uuid: string;\n name: string;\n country: string;\n languages: string[];\n timezone: string;\n date_style: DateStyle;\n anon: boolean;\n}\n\nexport interface Language {\n iso: string;\n name: string;\n}\n\nexport interface Attachment {\n uuid: string;\n content_type: string;\n url: string;\n filename: string;\n size: number;\n error: string;\n}\n\nexport enum DateStyle {\n DayFirst = 'day_first',\n MonthFirst = 'month_first',\n YearFirst = 'year_first'\n}\n\nexport enum ScheduledEventType {\n CampaignEvent = 'campaign_event',\n ScheduledBroadcast = 'scheduled_broadcast',\n ScheduledTrigger = 'scheduled_trigger'\n}\n\nexport enum TicketStatus {\n Open = 'open',\n Closed = 'closed'\n}\n\nexport interface ScheduledEvent {\n type: ScheduledEventType;\n scheduled: string;\n repeat_period: string;\n campaign?: ObjectReference;\n flow?: ObjectReference;\n message?: string;\n}\n\nexport interface NamedUser extends User {\n name: string;\n}\n\nexport interface User {\n id?: number;\n first_name?: string;\n last_name?: string;\n email?: string;\n role?: string;\n created_on?: string;\n avatar?: string;\n}\n\nexport interface Ticket {\n uuid: string;\n subject: string;\n body?: string;\n closed_on: string;\n opened_on: string;\n status: string;\n contact: ObjectReference;\n topic: ObjectReference;\n assignee?: { email: string; name: string; avatar?: string };\n}\n\nexport interface FlowResult {\n key: string;\n name: string;\n categories: string[];\n node_uuids: string[];\n}\n\nexport interface FlowDetails {\n name: string;\n results: FlowResult[];\n modified_on: string;\n runs: {\n active: number;\n completed: number;\n expired: number;\n interrupted: number;\n };\n}\n\nexport interface Msg {\n text: string;\n status: string;\n channel: ObjectReference;\n quick_replies: string[];\n urn: string;\n id: number;\n direction: string;\n type: string;\n attachments: string[];\n}\n\nexport interface ObjectReference {\n uuid: string;\n name: string;\n}\n\nexport interface Shortcut {\n uuid: string;\n name: string;\n text: string;\n modified_on: string;\n}\n\nexport interface ContactField {\n key: string;\n label: string;\n value_type: string;\n featured: boolean;\n priority: number;\n agent_access: string;\n type: string;\n usages: { campaign_events: number; flows: number; groups: number };\n}\n\nexport interface ContactGroup {\n uuid: string;\n count: number;\n name: string;\n query?: string;\n status: string;\n}\n\nexport interface URN {\n scheme: string;\n path: string;\n}\n\nexport interface Group {\n name: string;\n uuid: string;\n is_dynamic?: boolean;\n}\n\nexport interface ContactNote {\n text: string;\n created_on: string;\n created_by: NamedUser;\n}\n\nexport interface ContactTicket {\n name: string;\n uuid: string;\n status: string;\n\n contact: {\n uuid: string;\n name: string;\n created_on: Date;\n last_seen_on: Date;\n };\n}\n\nexport interface Contact {\n name: string;\n uuid: string;\n stopped: boolean;\n blocked: boolean;\n urns: string[];\n language?: string;\n fields: { [key: string]: string };\n groups: Group[];\n notes: ContactNote[];\n modified_on: string;\n created_on: string;\n last_seen_on: string;\n status: string;\n\n anon_display?: string;\n flow?: ObjectReference;\n last_msg?: Msg;\n direction?: string;\n ticket: {\n uuid: string;\n subject: string;\n closed_on?: string;\n last_activity_on: string;\n assignee?: User;\n topic?: ObjectReference;\n };\n}\n\nexport interface FeatureProperties {\n name: string;\n osm_id: string;\n level: number;\n children?: FeatureProperties[];\n has_children?: boolean;\n aliases?: string;\n parent_osm_id?: string;\n id?: number;\n path?: string;\n}\n\nexport interface Position {\n top: number;\n left: number;\n}\n\nexport interface FunctionExample {\n template: string;\n output: string;\n}\n\nexport interface CompletionOption {\n name?: string;\n summary: string;\n\n // functions\n signature?: string;\n detail?: string;\n examples?: FunctionExample[];\n}\n\nexport interface CompletionResult {\n anchorPosition: Position;\n query: string;\n options: CompletionOption[];\n currentFunction: CompletionOption;\n}\n\nexport interface CompletionProperty {\n key: string;\n help: string;\n type: string;\n}\n\nexport interface CompletionType {\n name: string;\n\n key_source?: string;\n property_template?: CompletionProperty;\n properties?: CompletionProperty[];\n}\n\nexport interface CompletionSchema {\n types: CompletionType[];\n root: CompletionProperty[];\n root_no_session: CompletionProperty[];\n}\n\nexport type KeyedAssets = { [assetType: string]: string[] };\n\nexport enum CustomEventType {\n Loaded = 'temba-loaded',\n Loading = 'temba-loading',\n Canceled = 'temba-canceled',\n CursorChanged = 'temba-cursor-changed',\n Refreshed = 'temba-refreshed',\n Selection = 'temba-selection',\n ButtonClicked = 'temba-button-clicked',\n DialogHidden = 'temba-dialog-hidden',\n ScrollThreshold = 'temba-scroll-threshold',\n ContentChanged = 'temba-content-changed',\n ContextChanged = 'temba-context-changed',\n FetchComplete = 'temba-fetch-complete',\n MessageSent = 'temba-message-sent',\n Submitted = 'temba-submitted',\n Redirected = 'temba-redirected',\n NoPath = 'temba-no-path',\n StoreUpdated = 'temba-store-updated',\n Ready = 'temba-ready',\n OrderChanged = 'temba-order-changed',\n DragStart = 'temba-drag-start',\n DragStop = 'temba-drag-stop',\n Resized = 'temba-resized',\n DetailsChanged = 'temba-details-changed'\n}\n"]}
@@ -0,0 +1,125 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, html } from 'lit';
3
+ import { property } from 'lit/decorators.js';
4
+ import { StoreMonitorElement } from '../store/StoreMonitorElement';
5
+ export class ShortcutList extends StoreMonitorElement {
6
+ static get styles() {
7
+ return css `
8
+ temba-options {
9
+ display: block;
10
+ width: 100%;
11
+ flex-grow: 1;
12
+ }
13
+
14
+ .options-empty {
15
+ height: 0;
16
+ overflow: hidden;
17
+ }
18
+
19
+ .no-match {
20
+ margin: 5px 10px;
21
+ padding: 10px;
22
+ }
23
+
24
+ .filter {
25
+ background: #f3f3f3;
26
+ padding: 0.1em 0.3em;
27
+ border-radius: var(--curvature);
28
+ }
29
+ `;
30
+ }
31
+ constructor() {
32
+ super();
33
+ this.filteredShortcuts = [];
34
+ this.cursorIndex = 0;
35
+ }
36
+ firstUpdated(changes) {
37
+ super.firstUpdated(changes);
38
+ }
39
+ storeUpdated() {
40
+ this.filteredShortcuts = this.store.getShortcuts();
41
+ }
42
+ updated(changes) {
43
+ super.updated(changes);
44
+ if (changes.has('filter')) {
45
+ if (!this.filter) {
46
+ this.filteredShortcuts = this.store.getShortcuts();
47
+ }
48
+ else {
49
+ this.filteredShortcuts = this.store
50
+ .getShortcuts()
51
+ .filter((shortcut) => shortcut.name.toLowerCase().includes(this.filter.toLowerCase()));
52
+ }
53
+ this.cursorIndex = 0;
54
+ }
55
+ }
56
+ renderShortcut(shortcut) {
57
+ return html `<div style="display:flex;align-items: center;min-width:0">
58
+ <div
59
+ style="
60
+ overflow: hidden;
61
+ text-overflow: ellipsis;
62
+ width:100px;
63
+ padding-right: 10px;
64
+ white-space: nowrap;"
65
+ >
66
+ ${shortcut.name}
67
+ </div>
68
+ <div
69
+ style="
70
+ font-size: 0.9em;
71
+ color: rgba(0, 0, 0, 0.4);
72
+ flex:1;
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+
76
+ display: -webkit-box;
77
+ line-height: 16px;
78
+ max-height: 16px;
79
+ -webkit-line-clamp: 1;
80
+ -webkit-box-orient: vertical;
81
+ "
82
+ >
83
+ ${shortcut.text}
84
+ </div>
85
+ </div>`;
86
+ }
87
+ getShortcut() {
88
+ const options = this.shadowRoot.querySelector('temba-options');
89
+ return options.getSelection();
90
+ }
91
+ render() {
92
+ return html `
93
+ ${this.filteredShortcuts.length === 0
94
+ ? html `<div class="no-match">
95
+ ${this.filter
96
+ ? html `No matches for <span class="filter">${this.filter}</span>.`
97
+ : html `No shortcuts yet, create some to quickly include them in
98
+ your messages.`}
99
+ </div>`
100
+ : null}
101
+
102
+ <temba-options
103
+ class="options-${this.filteredShortcuts.length === 0
104
+ ? 'empty'
105
+ : 'full'}"
106
+ block
107
+ cursorHover
108
+ visible
109
+ .renderOption=${this.renderShortcut}
110
+ .cursorIndex=${this.cursorIndex}
111
+ .options=${this.filteredShortcuts}
112
+ ></temba-options>
113
+ `;
114
+ }
115
+ }
116
+ __decorate([
117
+ property({ type: String })
118
+ ], ShortcutList.prototype, "filter", void 0);
119
+ __decorate([
120
+ property({ type: Array })
121
+ ], ShortcutList.prototype, "filteredShortcuts", void 0);
122
+ __decorate([
123
+ property({ type: Number })
124
+ ], ShortcutList.prototype, "cursorIndex", void 0);
125
+ //# sourceMappingURL=ShortcutList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShortcutList.js","sourceRoot":"","sources":["../../../src/list/ShortcutList.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAoC,MAAM,KAAK,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE,MAAM,OAAO,YAAa,SAAQ,mBAAmB;IACnD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;KAsBT,CAAC;IACJ,CAAC;IAWD;QACE,KAAK,EAAE,CAAC;QANV,sBAAiB,GAAG,EAAE,CAAC;QAGvB,gBAAW,GAAG,CAAC,CAAC;IAIhB,CAAC;IAES,YAAY,CACpB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAEM,YAAY;QACjB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;IACrD,CAAC;IAEM,OAAO,CACZ,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEvB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK;qBAChC,YAAY,EAAE;qBACd,MAAM,CAAC,CAAC,QAAkB,EAAE,EAAE,CAC7B,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAChE,CAAC;YACN,CAAC;YACD,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAEM,cAAc,CAAC,QAAkB;QACtC,OAAO,IAAI,CAAA;;;;;;;;;UASL,QAAQ,CAAC,IAAI;;;;;;;;;;;;;;;;;UAiBb,QAAQ,CAAC,IAAI;;WAEZ,CAAC;IACV,CAAC;IAEM,WAAW;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,eAAe,CAAY,CAAC;QAC1E,OAAO,OAAO,CAAC,YAAY,EAAE,CAAC;IAChC,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC;YACnC,CAAC,CAAC,IAAI,CAAA;cACA,IAAI,CAAC,MAAM;gBACX,CAAC,CAAC,IAAI,CAAA,uCAAuC,IAAI,CAAC,MAAM,UAAU;gBAClE,CAAC,CAAC,IAAI,CAAA;+BACW;iBACd;YACT,CAAC,CAAC,IAAI;;;yBAGW,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC;YAClD,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,MAAM;;;;wBAIM,IAAI,CAAC,cAAc;uBACpB,IAAI,CAAC,WAAW;mBACpB,IAAI,CAAC,iBAAiB;;KAEpC,CAAC;IACJ,CAAC;CACF;AAtGC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CACZ;AAGf;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;uDACH;AAGvB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iDACX","sourcesContent":["import { css, html, PropertyValueMap, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { Shortcut } from '../interfaces';\nimport { StoreMonitorElement } from '../store/StoreMonitorElement';\nimport { Options } from '../options/Options';\n\nexport class ShortcutList extends StoreMonitorElement {\n static get styles() {\n return css`\n temba-options {\n display: block;\n width: 100%;\n flex-grow: 1;\n }\n\n .options-empty {\n height: 0;\n overflow: hidden;\n }\n\n .no-match {\n margin: 5px 10px;\n padding: 10px;\n }\n\n .filter {\n background: #f3f3f3;\n padding: 0.1em 0.3em;\n border-radius: var(--curvature);\n }\n `;\n }\n\n @property({ type: String })\n filter: string;\n\n @property({ type: Array })\n filteredShortcuts = [];\n\n @property({ type: Number })\n cursorIndex = 0;\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n }\n\n public storeUpdated(): void {\n this.filteredShortcuts = this.store.getShortcuts();\n }\n\n public updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (changes.has('filter')) {\n if (!this.filter) {\n this.filteredShortcuts = this.store.getShortcuts();\n } else {\n this.filteredShortcuts = this.store\n .getShortcuts()\n .filter((shortcut: Shortcut) =>\n shortcut.name.toLowerCase().includes(this.filter.toLowerCase())\n );\n }\n this.cursorIndex = 0;\n }\n }\n\n public renderShortcut(shortcut: Shortcut): TemplateResult {\n return html`<div style=\"display:flex;align-items: center;min-width:0\">\n <div\n style=\"\n overflow: hidden;\n text-overflow: ellipsis;\n width:100px; \n padding-right: 10px;\n white-space: nowrap;\"\n >\n ${shortcut.name}\n </div>\n <div\n style=\" \n font-size: 0.9em;\n color: rgba(0, 0, 0, 0.4);\n flex:1;\n overflow: hidden;\n text-overflow: ellipsis;\n\n display: -webkit-box;\n line-height: 16px;\n max-height: 16px;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n \"\n >\n ${shortcut.text}\n </div>\n </div>`;\n }\n\n public getShortcut() {\n const options = this.shadowRoot.querySelector('temba-options') as Options;\n return options.getSelection();\n }\n\n public render(): TemplateResult {\n return html`\n ${this.filteredShortcuts.length === 0\n ? html`<div class=\"no-match\">\n ${this.filter\n ? html`No matches for <span class=\"filter\">${this.filter}</span>.`\n : html`No shortcuts yet, create some to quickly include them in\n your messages.`}\n </div>`\n : null}\n\n <temba-options\n class=\"options-${this.filteredShortcuts.length === 0\n ? 'empty'\n : 'full'}\"\n block\n cursorHover\n visible\n .renderOption=${this.renderShortcut}\n .cursorIndex=${this.cursorIndex}\n .options=${this.filteredShortcuts}\n ></temba-options>\n `;\n }\n}\n"]}
@@ -282,8 +282,6 @@ export class TembaList extends RapidElement {
282
282
  this.cursorIndex = 0;
283
283
  }
284
284
  }
285
- // TODO: Not sure why this is needed
286
- // this.requestUpdate('cursorIndex');
287
285
  if (this.value) {
288
286
  this.setSelection(this.value);
289
287
  this.value = null;
@@ -321,7 +319,11 @@ export class TembaList extends RapidElement {
321
319
  return '';
322
320
  }
323
321
  handleSelection(event) {
324
- const { selected, index } = event.detail;
322
+ let index = event.detail.index;
323
+ const selected = event.detail.selected;
324
+ if (index === -1) {
325
+ index = 0;
326
+ }
325
327
  this.selected = selected;
326
328
  this.cursorIndex = index;
327
329
  event.stopPropagation();
@@ -332,8 +334,9 @@ export class TembaList extends RapidElement {
332
334
  ${this.renderHeader()}
333
335
  <temba-options
334
336
  style="${this.getListStyle()}"
335
- ?visible=${true}
336
- ?block=${true}
337
+ visible
338
+ block
339
+ cursorSelection
337
340
  ?hideShadow=${this.hideShadow}
338
341
  ?collapsed=${this.collapsed}
339
342
  ?loading=${this.loading}
@@ -1 +1 @@
1
- {"version":3,"file":"TembaList.js","sourceRoot":"","sources":["../../../src/list/TembaList.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { CustomEventType } from '../interfaces';\nimport { RapidElement } from '../RapidElement';\nimport { Store } from '../store/Store';\nimport { fetchResultsPage, ResultsPage } from '../utils';\n\nconst DEFAULT_REFRESH = 10000;\n\nexport class TembaList extends RapidElement {\n @property({ type: Array, attribute: false })\n items: any[] = [];\n\n @property({ type: Object, attribute: false })\n selected: any;\n\n @property({ type: Number })\n cursorIndex = -1;\n\n @property({ type: String })\n endpoint: string;\n\n @property({ type: String })\n nextSelection: any;\n\n @property({ type: Number })\n tabIndex = 1;\n\n @property({ type: String })\n valueKey = 'id';\n\n @property({ type: String })\n value: string;\n\n @property({ type: Boolean })\n loading = false;\n\n @property({ type: Boolean })\n collapsed: boolean;\n\n @property({ type: Boolean })\n hideShadow: boolean;\n\n @property({ type: Boolean })\n paused = false;\n\n @property({ type: Boolean })\n internalFocusDisabled = false;\n\n @property({ attribute: false })\n getNextRefresh: (firstOption: any) => any;\n\n @property({ attribute: false })\n sanitizeOption: (option: any) => any;\n\n @property({ attribute: false })\n renderOption: (option: any, selected: boolean) => TemplateResult;\n\n @property({ attribute: false })\n renderOptionDetail: (option: any, selected: boolean) => TemplateResult;\n\n @property({ attribute: false, type: Object })\n mostRecentItem: any;\n\n // changes to the refresh key force a refresh\n @property({ type: String })\n refreshKey = '0';\n\n reverseRefresh = true;\n\n // our next page from our endpoint\n nextPage: string = null;\n\n pages = 0;\n clearRefreshTimeout: any;\n pending: AbortController[] = [];\n\n store: Store;\n\n // used for testing only\n preserve: boolean;\n\n static get styles() {\n return css`\n temba-options {\n display: block;\n width: 100%;\n flex-grow: 1;\n }\n `;\n }\n\n constructor() {\n super();\n this.store = document.querySelector('temba-store') as Store;\n this.handleSelection.bind(this);\n }\n\n private reset(): void {\n this.selected = null;\n this.nextPage = null;\n this.cursorIndex = -1;\n this.mostRecentItem = null;\n this.items = [];\n }\n\n refreshInterval = null;\n\n public connectedCallback() {\n super.connectedCallback();\n this.refreshInterval = setInterval(() => {\n if (!this.paused) {\n this.refreshKey = 'default_' + new Date().getTime();\n }\n }, DEFAULT_REFRESH);\n }\n\n public disconnectedCallback() {\n clearInterval(this.refreshInterval);\n }\n\n public updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('endpoint') && this.endpoint) {\n this.reset();\n this.loading = true;\n this.fetchItems();\n }\n\n if (changedProperties.has('loading')) {\n if (!this.loading) {\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }\n }\n\n if (\n changedProperties.has('refreshKey') &&\n !changedProperties.has('endpoint')\n ) {\n this.refreshTop();\n }\n\n if (changedProperties.has('mostRecentItem') && this.mostRecentItem) {\n this.fireCustomEvent(CustomEventType.Refreshed);\n }\n\n if (changedProperties.has('cursorIndex')) {\n if (this.cursorIndex > -1) {\n this.selected = this.items[this.cursorIndex];\n this.handleSelected(this.selected);\n }\n }\n\n if (changedProperties.has('items')) {\n //\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public handleSelected(selected: any) {\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n private getValue(obj: any): any {\n if (!obj) {\n return null;\n }\n\n const path = this.valueKey.split('.');\n let current = obj;\n while (path.length > 0) {\n const key = path.shift();\n current = current[key];\n }\n return current;\n }\n\n public setSelection(value: string) {\n const index = this.items.findIndex((item) => {\n return this.getValue(item) === value;\n });\n this.cursorIndex = index;\n this.selected = this.items[index];\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n public getItemIndex(value: string) {\n return this.items.findIndex((option) => this.getValue(option) === value);\n }\n\n public removeItem(value: string) {\n const index = this.getItemIndex(value);\n this.items.splice(index, 1);\n this.items = [...this.items];\n\n // if we were at the end, move us down\n this.cursorIndex = Math.max(\n 0,\n Math.min(this.items.length - 1, this.cursorIndex - 1)\n );\n\n // request a change even if it is the same, the item is different\n this.requestUpdate('cursorIndex');\n this.requestUpdate('items');\n }\n\n public getSelection(): any {\n return this.selected;\n }\n\n public refresh(): void {\n this.refreshKey = 'requested_' + new Date().getTime();\n }\n\n public setEndpoint(endpoint: string, nextSelection: any = null) {\n this.endpoint = endpoint;\n this.nextSelection = nextSelection;\n }\n\n public getRefreshEndpoint() {\n return this.endpoint;\n }\n\n /**\n * Refreshes the first page, updating any found items in our list\n */\n private async refreshTop(): Promise<void> {\n const refreshEndpoint = this.getRefreshEndpoint();\n if (!refreshEndpoint) {\n return;\n }\n\n // cancel any outstanding requests\n while (this.pending.length > 0) {\n const pending = this.pending.pop();\n pending.abort();\n }\n\n const controller = new AbortController();\n this.pending.push(controller);\n\n const prevItem = this.items[this.cursorIndex];\n\n try {\n const page = await fetchResultsPage(\n this.getRefreshEndpoint(),\n controller\n );\n\n const items = [...this.items];\n // remove any dupes already in our list\n if (page.results) {\n page.results.forEach((newOption: any) => {\n if (this.sanitizeOption) {\n this.sanitizeOption(newOption);\n }\n const newValue = this.getValue(newOption);\n const removeIndex = items.findIndex(\n (option) => this.getValue(option) === newValue\n );\n\n if (removeIndex > -1) {\n items.splice(removeIndex, 1);\n }\n });\n\n // insert our new items at the front\n let results = page.results;\n if (this.reverseRefresh) {\n results = page.results.reverse();\n }\n const newItems = [...results, ...items];\n\n const topItem = newItems[0];\n if (\n !this.mostRecentItem ||\n JSON.stringify(this.mostRecentItem) !== JSON.stringify(topItem)\n ) {\n this.mostRecentItem = topItem;\n }\n\n if (prevItem) {\n const newItem = newItems[this.cursorIndex];\n const prevValue = this.getValue(prevItem);\n if (prevValue !== this.getValue(newItem)) {\n const newIndex = newItems.findIndex(\n (option) => this.getValue(option) === prevValue\n );\n this.cursorIndex = newIndex;\n\n // make sure our focused item is visible\n window.setTimeout(() => {\n const options = this.shadowRoot.querySelector('temba-options');\n if (options) {\n const option =\n options.shadowRoot.querySelector('.option.focused');\n if (option) {\n option.scrollIntoView({ block: 'end', inline: 'nearest' });\n }\n }\n }, 0);\n }\n }\n\n this.items = newItems;\n }\n } catch (error) {\n // console.error(error);\n }\n }\n\n private async fetchItems(): Promise<void> {\n // cancel any outstanding requests\n while (this.pending.length > 0) {\n const pending = this.pending.pop();\n pending.abort();\n }\n\n let endpoint = this.endpoint;\n let pagesToFetch = this.pages || 1;\n let pages = 0;\n let nextPage = null;\n\n let fetchedItems: any[] = [];\n\n while (pagesToFetch > 0 && endpoint) {\n const controller = new AbortController();\n this.pending.push(controller);\n\n try {\n const page = await fetchResultsPage(endpoint, controller);\n\n // sanitize our options if necessary\n if (this.sanitizeOption) {\n page.results.forEach(this.sanitizeOption);\n }\n\n if (page.results) {\n fetchedItems = fetchedItems.concat(page.results);\n }\n\n // save our next pages\n nextPage = page.next;\n endpoint = nextPage;\n pagesToFetch--;\n pages++;\n } catch (error) {\n // aborted\n this.reset();\n console.log(error);\n return;\n }\n\n this.nextPage = nextPage;\n }\n this.pages = pages;\n\n const topItem = fetchedItems[0];\n if (\n !this.mostRecentItem ||\n JSON.stringify(this.mostRecentItem) !== JSON.stringify(topItem)\n ) {\n this.mostRecentItem = topItem;\n }\n\n // see if our cursor needs to move to stay on the same item\n const newItem = fetchedItems[this.cursorIndex];\n\n if (\n !this.nextSelection &&\n this.selected &&\n newItem &&\n this.getValue(newItem) !== this.getValue(this.selected)\n ) {\n const index = fetchedItems.findIndex((item) => {\n return this.getValue(item) === this.getValue(this.selected);\n });\n\n // old selection is in the new fetch\n if (index > -1) {\n this.cursorIndex = index;\n }\n // old selection is missing from the new fetch\n else {\n // if our index didn't change, our item still did, fire change\n if (this.cursorIndex === 0) {\n this.requestUpdate('cursorIndex');\n }\n // otherwise select the first item\n else {\n this.cursorIndex = 0;\n }\n }\n }\n\n // save our results\n this.items = fetchedItems;\n this.loading = false;\n this.pending = [];\n\n if (this.nextSelection) {\n this.setSelection(this.nextSelection);\n this.nextSelection = false;\n } else {\n if (this.cursorIndex === -1 && !this.isMobile()) {\n this.cursorIndex = 0;\n }\n }\n\n // TODO: Not sure why this is needed\n // this.requestUpdate('cursorIndex');\n\n if (this.value) {\n this.setSelection(this.value);\n this.value = null;\n } else if (this.isMobile() && !this.selected) {\n this.cursorIndex = -1;\n this.value = null;\n this.selected = null;\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n return Promise.resolve();\n }\n\n private handleScrollThreshold() {\n if (this.nextPage && !this.loading) {\n this.loading = true;\n fetchResultsPage(this.nextPage).then((page: ResultsPage) => {\n if (this.sanitizeOption) {\n page.results.forEach(this.sanitizeOption);\n }\n\n this.items = [...this.items, ...page.results];\n this.nextPage = page.next;\n this.pages++;\n this.loading = false;\n });\n }\n }\n\n public renderHeader(): TemplateResult {\n return null;\n }\n\n public renderFooter(): TemplateResult {\n return null;\n }\n\n public getListStyle() {\n return '';\n }\n\n protected handleSelection(event: CustomEvent) {\n const { selected, index } = event.detail;\n\n this.selected = selected;\n this.cursorIndex = index;\n\n event.stopPropagation();\n event.preventDefault();\n }\n\n public render(): TemplateResult {\n return html`\n ${this.renderHeader()}\n <temba-options\n style=\"${this.getListStyle()}\"\n ?visible=${true}\n ?block=${true}\n ?hideShadow=${this.hideShadow}\n ?collapsed=${this.collapsed}\n ?loading=${this.loading}\n ?internalFocusDisabled=${this.internalFocusDisabled}\n .renderOption=${this.renderOption}\n .renderOptionDetail=${this.renderOptionDetail}\n @temba-scroll-threshold=${this.handleScrollThreshold}\n @temba-selection=${this.handleSelection.bind(this)}\n .options=${this.items}\n .cursorIndex=${this.cursorIndex}\n >\n <slot></slot>\n </temba-options>\n ${this.renderFooter()}\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"TembaList.js","sourceRoot":"","sources":["../../../src/list/TembaList.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { CustomEventType } from '../interfaces';\nimport { RapidElement } from '../RapidElement';\nimport { Store } from '../store/Store';\nimport { fetchResultsPage, ResultsPage } from '../utils';\n\nconst DEFAULT_REFRESH = 10000;\n\nexport class TembaList extends RapidElement {\n @property({ type: Array, attribute: false })\n items: any[] = [];\n\n @property({ type: Object, attribute: false })\n selected: any;\n\n @property({ type: Number })\n cursorIndex = -1;\n\n @property({ type: String })\n endpoint: string;\n\n @property({ type: String })\n nextSelection: any;\n\n @property({ type: Number })\n tabIndex = 1;\n\n @property({ type: String })\n valueKey = 'id';\n\n @property({ type: String })\n value: string;\n\n @property({ type: Boolean })\n loading = false;\n\n @property({ type: Boolean })\n collapsed: boolean;\n\n @property({ type: Boolean })\n hideShadow: boolean;\n\n @property({ type: Boolean })\n paused = false;\n\n @property({ type: Boolean })\n internalFocusDisabled = false;\n\n @property({ attribute: false })\n getNextRefresh: (firstOption: any) => any;\n\n @property({ attribute: false })\n sanitizeOption: (option: any) => any;\n\n @property({ attribute: false })\n renderOption: (option: any, selected: boolean) => TemplateResult;\n\n @property({ attribute: false })\n renderOptionDetail: (option: any, selected: boolean) => TemplateResult;\n\n @property({ attribute: false, type: Object })\n mostRecentItem: any;\n\n // changes to the refresh key force a refresh\n @property({ type: String })\n refreshKey = '0';\n\n reverseRefresh = true;\n\n // our next page from our endpoint\n nextPage: string = null;\n\n pages = 0;\n clearRefreshTimeout: any;\n pending: AbortController[] = [];\n\n store: Store;\n\n // used for testing only\n preserve: boolean;\n\n static get styles() {\n return css`\n temba-options {\n display: block;\n width: 100%;\n flex-grow: 1;\n }\n `;\n }\n\n constructor() {\n super();\n this.store = document.querySelector('temba-store') as Store;\n this.handleSelection.bind(this);\n }\n\n private reset(): void {\n this.selected = null;\n this.nextPage = null;\n this.cursorIndex = -1;\n this.mostRecentItem = null;\n this.items = [];\n }\n\n refreshInterval = null;\n\n public connectedCallback() {\n super.connectedCallback();\n this.refreshInterval = setInterval(() => {\n if (!this.paused) {\n this.refreshKey = 'default_' + new Date().getTime();\n }\n }, DEFAULT_REFRESH);\n }\n\n public disconnectedCallback() {\n clearInterval(this.refreshInterval);\n }\n\n public updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n\n if (changedProperties.has('endpoint') && this.endpoint) {\n this.reset();\n this.loading = true;\n this.fetchItems();\n }\n\n if (changedProperties.has('loading')) {\n if (!this.loading) {\n this.fireCustomEvent(CustomEventType.FetchComplete);\n }\n }\n\n if (\n changedProperties.has('refreshKey') &&\n !changedProperties.has('endpoint')\n ) {\n this.refreshTop();\n }\n\n if (changedProperties.has('mostRecentItem') && this.mostRecentItem) {\n this.fireCustomEvent(CustomEventType.Refreshed);\n }\n\n if (changedProperties.has('cursorIndex')) {\n if (this.cursorIndex > -1) {\n this.selected = this.items[this.cursorIndex];\n this.handleSelected(this.selected);\n }\n }\n\n if (changedProperties.has('items')) {\n //\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public handleSelected(selected: any) {\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n private getValue(obj: any): any {\n if (!obj) {\n return null;\n }\n\n const path = this.valueKey.split('.');\n let current = obj;\n while (path.length > 0) {\n const key = path.shift();\n current = current[key];\n }\n return current;\n }\n\n public setSelection(value: string) {\n const index = this.items.findIndex((item) => {\n return this.getValue(item) === value;\n });\n this.cursorIndex = index;\n this.selected = this.items[index];\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n public getItemIndex(value: string) {\n return this.items.findIndex((option) => this.getValue(option) === value);\n }\n\n public removeItem(value: string) {\n const index = this.getItemIndex(value);\n this.items.splice(index, 1);\n this.items = [...this.items];\n\n // if we were at the end, move us down\n this.cursorIndex = Math.max(\n 0,\n Math.min(this.items.length - 1, this.cursorIndex - 1)\n );\n\n // request a change even if it is the same, the item is different\n this.requestUpdate('cursorIndex');\n this.requestUpdate('items');\n }\n\n public getSelection(): any {\n return this.selected;\n }\n\n public refresh(): void {\n this.refreshKey = 'requested_' + new Date().getTime();\n }\n\n public setEndpoint(endpoint: string, nextSelection: any = null) {\n this.endpoint = endpoint;\n this.nextSelection = nextSelection;\n }\n\n public getRefreshEndpoint() {\n return this.endpoint;\n }\n\n /**\n * Refreshes the first page, updating any found items in our list\n */\n private async refreshTop(): Promise<void> {\n const refreshEndpoint = this.getRefreshEndpoint();\n if (!refreshEndpoint) {\n return;\n }\n\n // cancel any outstanding requests\n while (this.pending.length > 0) {\n const pending = this.pending.pop();\n pending.abort();\n }\n\n const controller = new AbortController();\n this.pending.push(controller);\n\n const prevItem = this.items[this.cursorIndex];\n\n try {\n const page = await fetchResultsPage(\n this.getRefreshEndpoint(),\n controller\n );\n\n const items = [...this.items];\n // remove any dupes already in our list\n if (page.results) {\n page.results.forEach((newOption: any) => {\n if (this.sanitizeOption) {\n this.sanitizeOption(newOption);\n }\n const newValue = this.getValue(newOption);\n const removeIndex = items.findIndex(\n (option) => this.getValue(option) === newValue\n );\n\n if (removeIndex > -1) {\n items.splice(removeIndex, 1);\n }\n });\n\n // insert our new items at the front\n let results = page.results;\n if (this.reverseRefresh) {\n results = page.results.reverse();\n }\n const newItems = [...results, ...items];\n\n const topItem = newItems[0];\n if (\n !this.mostRecentItem ||\n JSON.stringify(this.mostRecentItem) !== JSON.stringify(topItem)\n ) {\n this.mostRecentItem = topItem;\n }\n\n if (prevItem) {\n const newItem = newItems[this.cursorIndex];\n const prevValue = this.getValue(prevItem);\n if (prevValue !== this.getValue(newItem)) {\n const newIndex = newItems.findIndex(\n (option) => this.getValue(option) === prevValue\n );\n this.cursorIndex = newIndex;\n\n // make sure our focused item is visible\n window.setTimeout(() => {\n const options = this.shadowRoot.querySelector('temba-options');\n if (options) {\n const option =\n options.shadowRoot.querySelector('.option.focused');\n if (option) {\n option.scrollIntoView({ block: 'end', inline: 'nearest' });\n }\n }\n }, 0);\n }\n }\n\n this.items = newItems;\n }\n } catch (error) {\n // console.error(error);\n }\n }\n\n private async fetchItems(): Promise<void> {\n // cancel any outstanding requests\n while (this.pending.length > 0) {\n const pending = this.pending.pop();\n pending.abort();\n }\n\n let endpoint = this.endpoint;\n let pagesToFetch = this.pages || 1;\n let pages = 0;\n let nextPage = null;\n\n let fetchedItems: any[] = [];\n\n while (pagesToFetch > 0 && endpoint) {\n const controller = new AbortController();\n this.pending.push(controller);\n\n try {\n const page = await fetchResultsPage(endpoint, controller);\n\n // sanitize our options if necessary\n if (this.sanitizeOption) {\n page.results.forEach(this.sanitizeOption);\n }\n\n if (page.results) {\n fetchedItems = fetchedItems.concat(page.results);\n }\n\n // save our next pages\n nextPage = page.next;\n endpoint = nextPage;\n pagesToFetch--;\n pages++;\n } catch (error) {\n // aborted\n this.reset();\n console.log(error);\n return;\n }\n\n this.nextPage = nextPage;\n }\n this.pages = pages;\n\n const topItem = fetchedItems[0];\n if (\n !this.mostRecentItem ||\n JSON.stringify(this.mostRecentItem) !== JSON.stringify(topItem)\n ) {\n this.mostRecentItem = topItem;\n }\n\n // see if our cursor needs to move to stay on the same item\n const newItem = fetchedItems[this.cursorIndex];\n\n if (\n !this.nextSelection &&\n this.selected &&\n newItem &&\n this.getValue(newItem) !== this.getValue(this.selected)\n ) {\n const index = fetchedItems.findIndex((item) => {\n return this.getValue(item) === this.getValue(this.selected);\n });\n\n // old selection is in the new fetch\n if (index > -1) {\n this.cursorIndex = index;\n }\n // old selection is missing from the new fetch\n else {\n // if our index didn't change, our item still did, fire change\n if (this.cursorIndex === 0) {\n this.requestUpdate('cursorIndex');\n }\n // otherwise select the first item\n else {\n this.cursorIndex = 0;\n }\n }\n }\n\n // save our results\n this.items = fetchedItems;\n this.loading = false;\n this.pending = [];\n\n if (this.nextSelection) {\n this.setSelection(this.nextSelection);\n this.nextSelection = false;\n } else {\n if (this.cursorIndex === -1 && !this.isMobile()) {\n this.cursorIndex = 0;\n }\n }\n\n if (this.value) {\n this.setSelection(this.value);\n this.value = null;\n } else if (this.isMobile() && !this.selected) {\n this.cursorIndex = -1;\n this.value = null;\n this.selected = null;\n const evt = new Event('change', { bubbles: true });\n this.dispatchEvent(evt);\n }\n\n return Promise.resolve();\n }\n\n private handleScrollThreshold() {\n if (this.nextPage && !this.loading) {\n this.loading = true;\n fetchResultsPage(this.nextPage).then((page: ResultsPage) => {\n if (this.sanitizeOption) {\n page.results.forEach(this.sanitizeOption);\n }\n\n this.items = [...this.items, ...page.results];\n this.nextPage = page.next;\n this.pages++;\n this.loading = false;\n });\n }\n }\n\n public renderHeader(): TemplateResult {\n return null;\n }\n\n public renderFooter(): TemplateResult {\n return null;\n }\n\n public getListStyle() {\n return '';\n }\n\n protected handleSelection(event: CustomEvent) {\n let index = event.detail.index;\n const selected = event.detail.selected;\n\n if (index === -1) {\n index = 0;\n }\n\n this.selected = selected;\n this.cursorIndex = index;\n\n event.stopPropagation();\n event.preventDefault();\n }\n\n public render(): TemplateResult {\n return html`\n ${this.renderHeader()}\n <temba-options\n style=\"${this.getListStyle()}\"\n visible\n block\n cursorSelection\n ?hideShadow=${this.hideShadow}\n ?collapsed=${this.collapsed}\n ?loading=${this.loading}\n ?internalFocusDisabled=${this.internalFocusDisabled}\n .renderOption=${this.renderOption}\n .renderOptionDetail=${this.renderOptionDetail}\n @temba-scroll-threshold=${this.handleScrollThreshold}\n @temba-selection=${this.handleSelection.bind(this)}\n .options=${this.items}\n .cursorIndex=${this.cursorIndex}\n >\n <slot></slot>\n </temba-options>\n ${this.renderFooter()}\n `;\n }\n}\n"]}
@@ -133,6 +133,7 @@ export class Options extends RapidElement {
133
133
  margin: 0.3em;
134
134
  cursor: pointer;
135
135
  color: var(--color-text-dark);
136
+ scroll-margin: 5px 0px;
136
137
  }
137
138
 
138
139
  .option * {
@@ -223,52 +224,34 @@ export class Options extends RapidElement {
223
224
  document.activeElement;
224
225
  return focused;
225
226
  }
226
- updated(changedProperties) {
227
- super.updated(changedProperties);
227
+ updated(changed) {
228
+ super.updated(changed);
228
229
  // if our cursor changed, lets make sure our scrollbox is showing it
229
- if (!this.internalFocusDisabled && changedProperties.has('cursorIndex')) {
230
- const focusedOption = this.shadowRoot.querySelector(`div[data-option-index="${this.cursorIndex}"]`);
231
- if (focusedOption) {
232
- const scrollBox = this.shadowRoot.querySelector('.options-container');
233
- const scrollBoxRect = scrollBox.getBoundingClientRect();
234
- const scrollBoxHeight = scrollBoxRect.height;
235
- const focusedEleHeight = focusedOption.getBoundingClientRect().height;
236
- if (focusedOption.offsetTop + focusedEleHeight >
237
- scrollBox.scrollTop + scrollBoxHeight - 5) {
238
- const scrollTo = focusedOption.offsetTop - scrollBoxHeight + focusedEleHeight + 5;
239
- scrollBox.scrollTop = scrollTo;
240
- }
241
- else if (focusedOption.offsetTop < scrollBox.scrollTop) {
242
- const scrollTo = focusedOption.offsetTop - 5;
243
- scrollBox.scrollTop = scrollTo;
244
- }
245
- }
230
+ if (!this.internalFocusDisabled && changed.has('cursorIndex')) {
246
231
  this.fireCustomEvent(CustomEventType.CursorChanged, {
247
232
  index: this.cursorIndex
248
233
  });
249
234
  }
250
- if (changedProperties.has('visible') && changedProperties.has('options')) {
235
+ if (changed.has('visible') && changed.has('options')) {
251
236
  if (!this.visible && this.options.length == 0) {
252
- this.tempOptions = changedProperties.get('options');
237
+ this.tempOptions = changed.get('options');
253
238
  window.setTimeout(() => {
254
239
  this.tempOptions = [];
255
240
  }, 300);
256
241
  }
257
242
  }
258
- if (changedProperties.has('options')) {
243
+ if (changed.has('options')) {
259
244
  this.calculatePosition();
260
245
  // allow scrolls to trigger again
261
246
  this.triggerScroll = true;
262
- const prevOptions = changedProperties.get('options');
247
+ const prevOptions = changed.get('options');
263
248
  const previousCount = prevOptions ? prevOptions.length : 0;
264
249
  const newCount = this.options ? this.options.length : 0;
265
250
  if (this.cursorIndex === -1 ||
266
251
  newCount < previousCount ||
267
- (previousCount === 0 &&
268
- newCount > 0 &&
269
- !changedProperties.has('cursorIndex'))) {
252
+ (previousCount === 0 && newCount > 0 && !changed.has('cursorIndex'))) {
270
253
  if (!this.internalFocusDisabled) {
271
- if (!this.block) {
254
+ if (!this.block || this.cursorIndex === -1) {
272
255
  this.cursorIndex = 0;
273
256
  }
274
257
  else {
@@ -276,7 +259,7 @@ export class Options extends RapidElement {
276
259
  this.cursorIndex = newCount - 1;
277
260
  }
278
261
  }
279
- if (this.block) {
262
+ if (this.cursorSelection) {
280
263
  this.handleSelection(false);
281
264
  }
282
265
  }
@@ -284,11 +267,13 @@ export class Options extends RapidElement {
284
267
  // if on initial load we don't have enough options to load, trigger a scroll
285
268
  // threshold event in case the page size is smaller than our control height
286
269
  const scrollBox = this.shadowRoot.querySelector('.options');
287
- if (scrollBox.scrollHeight == scrollBox.clientHeight) {
288
- this.fireCustomEvent(CustomEventType.ScrollThreshold);
270
+ if (scrollBox) {
271
+ if (scrollBox.scrollHeight == scrollBox.clientHeight) {
272
+ this.fireCustomEvent(CustomEventType.ScrollThreshold);
273
+ }
289
274
  }
290
275
  }
291
- if (changedProperties.has('visible')) {
276
+ if (changed.has('visible')) {
292
277
  window.setTimeout(() => {
293
278
  this.calculatePosition();
294
279
  }, 100);
@@ -323,6 +308,9 @@ export class Options extends RapidElement {
323
308
  renderOptionDetailDefault(option) {
324
309
  return html ` ${option.detail} `;
325
310
  }
311
+ getSelection() {
312
+ return this.options[this.cursorIndex];
313
+ }
326
314
  handleSelection(tabbed = false, index = -1) {
327
315
  if (!this.internalFocusDisabled) {
328
316
  if (index === -1) {
@@ -346,25 +334,39 @@ export class Options extends RapidElement {
346
334
  const scrollBox = this.shadowRoot.querySelector('.options-scroll');
347
335
  scrollBox.scrollTop = 0;
348
336
  }
337
+ ensureOptionVisible() {
338
+ const focusedOption = this.shadowRoot.querySelector(`div[data-option-index="${this.cursorIndex}"]`);
339
+ if (focusedOption) {
340
+ focusedOption.scrollIntoView({
341
+ block: 'nearest',
342
+ inline: 'start'
343
+ });
344
+ }
345
+ }
349
346
  handleKeyDown(evt) {
350
347
  if (this.internalFocusDisabled || (this.block && !this.isFocused())) {
351
348
  return;
352
349
  }
350
+ if (this.offsetParent === null) {
351
+ return;
352
+ }
353
353
  if (this.options && this.options.length > 0) {
354
354
  if ((evt.ctrlKey && evt.key === 'n') || evt.key === 'ArrowDown') {
355
355
  this.moveCursor(1);
356
356
  evt.preventDefault();
357
357
  evt.stopPropagation();
358
- if (this.block) {
358
+ if (this.cursorSelection) {
359
359
  this.handleSelection(false);
360
360
  }
361
+ this.ensureOptionVisible();
361
362
  }
362
363
  else if ((evt.ctrlKey && evt.key === 'p') || evt.key === 'ArrowUp') {
363
364
  this.moveCursor(-1);
364
365
  evt.preventDefault();
365
- if (this.block) {
366
+ if (this.cursorSelection) {
366
367
  this.handleSelection(false);
367
368
  }
369
+ this.ensureOptionVisible();
368
370
  }
369
371
  else if (evt.key === 'Enter' ||
370
372
  evt.key === 'Tab' ||
@@ -373,7 +375,7 @@ export class Options extends RapidElement {
373
375
  evt.stopPropagation();
374
376
  this.handleSelection(evt.key === 'Tab');
375
377
  }
376
- if (evt.key === 'Escape') {
378
+ else if (evt.key === 'Escape') {
377
379
  this.fireCustomEvent(CustomEventType.Canceled);
378
380
  }
379
381
  }
@@ -441,7 +443,7 @@ export class Options extends RapidElement {
441
443
  ];
442
444
  }
443
445
  handleMouseMove(evt) {
444
- if (!this.block) {
446
+ if (!this.block || this.cursorHover) {
445
447
  if (Math.abs(evt.movementX) + Math.abs(evt.movementY) > 0) {
446
448
  const index = evt.currentTarget.getAttribute('data-option-index');
447
449
  this.setCursor(parseInt(index));
@@ -464,6 +466,9 @@ export class Options extends RapidElement {
464
466
  }
465
467
  }
466
468
  render() {
469
+ if (!this.resolvedRenderOption) {
470
+ return null;
471
+ }
467
472
  let vertical = this.block ? 0 : this.marginVertical;
468
473
  if (this.poppedTop) {
469
474
  vertical *= -1;
@@ -564,6 +569,12 @@ __decorate([
564
569
  __decorate([
565
570
  property({ type: Boolean })
566
571
  ], Options.prototype, "block", void 0);
572
+ __decorate([
573
+ property({ type: Boolean })
574
+ ], Options.prototype, "cursorHover", void 0);
575
+ __decorate([
576
+ property({ type: Boolean })
577
+ ], Options.prototype, "cursorSelection", void 0);
567
578
  __decorate([
568
579
  property({ type: Number })
569
580
  ], Options.prototype, "scrollPct", void 0);