@dialpad/dialtone-vue 4.4.1 → 4.5.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 (196) hide show
  1. package/dist/{Datepicker-CGFa1nGm.js → Datepicker-D-Lgvthq.js} +17 -5
  2. package/dist/Datepicker-D-Lgvthq.js.map +1 -0
  3. package/dist/Datepicker-DmKOuf5y.cjs +2 -0
  4. package/dist/Datepicker-DmKOuf5y.cjs.map +1 -0
  5. package/dist/EmojiPicker-CXFd-iVj.cjs +2 -0
  6. package/dist/EmojiPicker-CXFd-iVj.cjs.map +1 -0
  7. package/dist/{EmojiPicker-BllVwJf4.js → EmojiPicker-D46lLRMp.js} +75 -41
  8. package/dist/EmojiPicker-D46lLRMp.js.map +1 -0
  9. package/dist/{ForceLinkify-bO3ug94b.js → ForceLinkify-DuAo3TMB.js} +1 -1
  10. package/dist/{ForceLinkify-bO3ug94b.js.map → ForceLinkify-DuAo3TMB.js.map} +1 -1
  11. package/dist/{ForceLinkify-CI1tkUBf.cjs → ForceLinkify-kQ_kWKVm.cjs} +1 -1
  12. package/dist/{ForceLinkify-CI1tkUBf.cjs.map → ForceLinkify-kQ_kWKVm.cjs.map} +1 -1
  13. package/dist/{MarkdownRenderer-B6oyniLV.cjs → MarkdownRenderer-C5wdjC5_.cjs} +1 -1
  14. package/dist/{MarkdownRenderer-B6oyniLV.cjs.map → MarkdownRenderer-C5wdjC5_.cjs.map} +1 -1
  15. package/dist/{MarkdownRenderer-D-EV50_M.js → MarkdownRenderer-eMwmPygx.js} +1 -1
  16. package/dist/{MarkdownRenderer-D-EV50_M.js.map → MarkdownRenderer-eMwmPygx.js.map} +1 -1
  17. package/dist/RichTextEditor-7eY8gy9u.cjs +11 -0
  18. package/dist/RichTextEditor-7eY8gy9u.cjs.map +1 -0
  19. package/dist/{RichTextEditor-Cz2VXb7-.js → RichTextEditor-DaOHmXD_.js} +362 -1254
  20. package/dist/RichTextEditor-DaOHmXD_.js.map +1 -0
  21. package/dist/{Scroller-JDoDYC5V.js → Scroller-B1xwv6TG.js} +1 -1
  22. package/dist/{Scroller-JDoDYC5V.js.map → Scroller-B1xwv6TG.js.map} +1 -1
  23. package/dist/{Scroller-Du2kJsTR.cjs → Scroller-pAU8UWIH.cjs} +1 -1
  24. package/dist/{Scroller-Du2kJsTR.cjs.map → Scroller-pAU8UWIH.cjs.map} +1 -1
  25. package/dist/Slider-D2cDYZcJ.cjs +2 -0
  26. package/dist/Slider-D2cDYZcJ.cjs.map +1 -0
  27. package/dist/Slider-Du45PVLU.js +1188 -0
  28. package/dist/Slider-Du45PVLU.js.map +1 -0
  29. package/dist/{TextList-D40u4g4T.js → TextList-7RwngSie.js} +1 -1
  30. package/dist/{TextList-D40u4g4T.js.map → TextList-7RwngSie.js.map} +1 -1
  31. package/dist/{TextList-rS1MQdPB.cjs → TextList-CLUdOdlp.cjs} +1 -1
  32. package/dist/{TextList-rS1MQdPB.cjs.map → TextList-CLUdOdlp.cjs.map} +1 -1
  33. package/dist/{TextListItem-CF6DzdvT.cjs → TextListItem-B-bhrqik.cjs} +1 -1
  34. package/dist/{TextListItem-CF6DzdvT.cjs.map → TextListItem-B-bhrqik.cjs.map} +1 -1
  35. package/dist/{TextListItem-PHgDIWV1.js → TextListItem-D0UmIR_q.js} +1 -1
  36. package/dist/{TextListItem-PHgDIWV1.js.map → TextListItem-D0UmIR_q.js.map} +1 -1
  37. package/dist/{Toast-CN9x3jKH.cjs → Toast-57Ts-hX9.cjs} +1 -1
  38. package/dist/{Toast-CN9x3jKH.cjs.map → Toast-57Ts-hX9.cjs.map} +1 -1
  39. package/dist/{Toast-DVUE2_fV.js → Toast-BNhGD6l8.js} +1 -1
  40. package/dist/{Toast-DVUE2_fV.js.map → Toast-BNhGD6l8.js.map} +1 -1
  41. package/dist/component-documentation.json +1 -1
  42. package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts.map +1 -1
  43. package/dist/components/Codeblock/Codeblock.vue.d.ts.map +1 -1
  44. package/dist/components/Datepicker/Datepicker.vue.d.ts.map +1 -1
  45. package/dist/components/Datepicker/Modules/Calendar.vue.d.ts.map +1 -1
  46. package/dist/components/Datepicker/Modules/MonthYearPicker.vue.d.ts.map +1 -1
  47. package/dist/components/DescriptionList/DescriptionList.vue.d.ts.map +1 -1
  48. package/dist/components/Emoji/Emoji.vue.d.ts.map +1 -1
  49. package/dist/components/EmojiPicker/EmojiPicker.vue.d.ts.map +1 -1
  50. package/dist/components/EmojiPicker/Modules/EmojiDescription.vue.d.ts.map +1 -1
  51. package/dist/components/EmojiPicker/Modules/EmojiSearch.vue.d.ts.map +1 -1
  52. package/dist/components/EmojiPicker/Modules/EmojiSelector.vue.d.ts.map +1 -1
  53. package/dist/components/EmojiPicker/Modules/EmojiSkinSelector.vue.d.ts.map +1 -1
  54. package/dist/components/EmojiPicker/Modules/EmojiTabset.vue.d.ts.map +1 -1
  55. package/dist/components/EmptyState/EmptyState.vue.d.ts.map +1 -1
  56. package/dist/components/KeyboardShortcut/KeyboardShortcut.vue.d.ts.map +1 -1
  57. package/dist/components/LazyShow/LazyShow.vue.d.ts.map +1 -1
  58. package/dist/components/ModeIsland/ModeIsland.vue.d.ts.map +1 -1
  59. package/dist/components/MotionText/MotionText.vue.d.ts.map +1 -1
  60. package/dist/components/MotionText/MotionTextConstants.d.ts +72 -0
  61. package/dist/components/MotionText/MotionTextConstants.d.ts.map +1 -1
  62. package/dist/components/MotionText/index.d.ts +1 -1
  63. package/dist/components/MotionText/utils.d.ts +9 -0
  64. package/dist/components/MotionText/utils.d.ts.map +1 -0
  65. package/dist/components/Skeleton/Skeleton.vue.d.ts.map +1 -1
  66. package/dist/components/Slider/Composables/UseSliderCollisionAvoidance.d.ts +25 -0
  67. package/dist/components/Slider/Composables/UseSliderCollisionAvoidance.d.ts.map +1 -0
  68. package/dist/components/Slider/Composables/UseSliderDevWarnings.d.ts +5 -0
  69. package/dist/components/Slider/Composables/UseSliderDevWarnings.d.ts.map +1 -0
  70. package/dist/components/Slider/Composables/UseSliderDirection.d.ts +4 -0
  71. package/dist/components/Slider/Composables/UseSliderDirection.d.ts.map +1 -0
  72. package/dist/components/Slider/Composables/UseSliderGeometry.d.ts +88 -0
  73. package/dist/components/Slider/Composables/UseSliderGeometry.d.ts.map +1 -0
  74. package/dist/components/Slider/Composables/UseSliderInteraction.d.ts +33 -0
  75. package/dist/components/Slider/Composables/UseSliderInteraction.d.ts.map +1 -0
  76. package/dist/components/Slider/Composables/UseSliderMagneticSnap.d.ts +8 -0
  77. package/dist/components/Slider/Composables/UseSliderMagneticSnap.d.ts.map +1 -0
  78. package/dist/components/Slider/Composables/UseSliderMarksAndTicks.d.ts +13 -0
  79. package/dist/components/Slider/Composables/UseSliderMarksAndTicks.d.ts.map +1 -0
  80. package/dist/components/Slider/Composables/UseSliderTooltipReadout.d.ts +10 -0
  81. package/dist/components/Slider/Composables/UseSliderTooltipReadout.d.ts.map +1 -0
  82. package/dist/components/Slider/Composables/UseSliderValue.d.ts +16 -0
  83. package/dist/components/Slider/Composables/UseSliderValue.d.ts.map +1 -0
  84. package/dist/components/Slider/Slider.vue.d.ts +304 -0
  85. package/dist/components/Slider/Slider.vue.d.ts.map +1 -0
  86. package/dist/components/Slider/SliderConstants.d.ts +7 -0
  87. package/dist/components/Slider/SliderConstants.d.ts.map +1 -0
  88. package/dist/components/Slider/index.d.ts +3 -0
  89. package/dist/components/Slider/index.d.ts.map +1 -0
  90. package/dist/components/Slider/utils.d.ts +8 -0
  91. package/dist/components/Slider/utils.d.ts.map +1 -0
  92. package/dist/dialtone-vue.cjs +1 -1
  93. package/dist/dialtone-vue.js +26 -24
  94. package/dist/floating-ui.dom-D2zQ_96p.cjs +2 -0
  95. package/dist/floating-ui.dom-D2zQ_96p.cjs.map +1 -0
  96. package/dist/floating-ui.dom-j5GI2lJG.js +963 -0
  97. package/dist/floating-ui.dom-j5GI2lJG.js.map +1 -0
  98. package/dist/index.d.ts +1 -0
  99. package/dist/lib/button-group/button-group.cjs +1 -1
  100. package/dist/lib/button-group/button-group.cjs.map +1 -1
  101. package/dist/lib/button-group/button-group.js +2 -1
  102. package/dist/lib/button-group/button-group.js.map +1 -1
  103. package/dist/lib/codeblock/codeblock.cjs +1 -1
  104. package/dist/lib/codeblock/codeblock.cjs.map +1 -1
  105. package/dist/lib/codeblock/codeblock.js +7 -1
  106. package/dist/lib/codeblock/codeblock.js.map +1 -1
  107. package/dist/lib/datepicker/datepicker.cjs +1 -1
  108. package/dist/lib/datepicker/datepicker.js +1 -1
  109. package/dist/lib/datepicker/index.cjs +1 -1
  110. package/dist/lib/datepicker/index.js +1 -1
  111. package/dist/lib/description-list/description-list.cjs +1 -1
  112. package/dist/lib/description-list/description-list.cjs.map +1 -1
  113. package/dist/lib/description-list/description-list.js +14 -5
  114. package/dist/lib/description-list/description-list.js.map +1 -1
  115. package/dist/lib/emoji/emoji.cjs +1 -1
  116. package/dist/lib/emoji/emoji.cjs.map +1 -1
  117. package/dist/lib/emoji/emoji.js +5 -1
  118. package/dist/lib/emoji/emoji.js.map +1 -1
  119. package/dist/lib/emoji-picker/emoji-picker.cjs +1 -1
  120. package/dist/lib/emoji-picker/emoji-picker.js +1 -1
  121. package/dist/lib/emoji-picker/index.cjs +1 -1
  122. package/dist/lib/emoji-picker/index.js +1 -1
  123. package/dist/lib/empty-state/empty-state.cjs +1 -1
  124. package/dist/lib/empty-state/empty-state.cjs.map +1 -1
  125. package/dist/lib/empty-state/empty-state.js +6 -3
  126. package/dist/lib/empty-state/empty-state.js.map +1 -1
  127. package/dist/lib/keyboard-shortcut/keyboard-shortcut.cjs +1 -1
  128. package/dist/lib/keyboard-shortcut/keyboard-shortcut.cjs.map +1 -1
  129. package/dist/lib/keyboard-shortcut/keyboard-shortcut.js +8 -2
  130. package/dist/lib/keyboard-shortcut/keyboard-shortcut.js.map +1 -1
  131. package/dist/lib/lazy-show/lazy-show.cjs +1 -1
  132. package/dist/lib/lazy-show/lazy-show.cjs.map +1 -1
  133. package/dist/lib/lazy-show/lazy-show.js +10 -10
  134. package/dist/lib/lazy-show/lazy-show.js.map +1 -1
  135. package/dist/lib/mode-island/mode-island.cjs +1 -1
  136. package/dist/lib/mode-island/mode-island.cjs.map +1 -1
  137. package/dist/lib/mode-island/mode-island.js +1 -0
  138. package/dist/lib/mode-island/mode-island.js.map +1 -1
  139. package/dist/lib/motion-text/index.cjs +1 -1
  140. package/dist/lib/motion-text/index.js +3 -3
  141. package/dist/lib/motion-text/motion-text-constants.cjs +1 -1
  142. package/dist/lib/motion-text/motion-text-constants.cjs.map +1 -1
  143. package/dist/lib/motion-text/motion-text-constants.js +64 -2
  144. package/dist/lib/motion-text/motion-text-constants.js.map +1 -1
  145. package/dist/lib/motion-text/motion-text.cjs +1 -1
  146. package/dist/lib/motion-text/motion-text.cjs.map +1 -1
  147. package/dist/lib/motion-text/motion-text.js +186 -146
  148. package/dist/lib/motion-text/motion-text.js.map +1 -1
  149. package/dist/lib/motion-text/utils.cjs +2 -0
  150. package/dist/lib/motion-text/utils.cjs.map +1 -0
  151. package/dist/lib/motion-text/utils.js +24 -0
  152. package/dist/lib/motion-text/utils.js.map +1 -0
  153. package/dist/lib/rich-text-editor/force-linkify.cjs +1 -1
  154. package/dist/lib/rich-text-editor/force-linkify.js +1 -1
  155. package/dist/lib/rich-text-editor/index.cjs +1 -1
  156. package/dist/lib/rich-text-editor/index.js +1 -1
  157. package/dist/lib/rich-text-editor/markdown-renderer.cjs +1 -1
  158. package/dist/lib/rich-text-editor/markdown-renderer.js +1 -1
  159. package/dist/lib/rich-text-editor/rich-text-editor.cjs +1 -1
  160. package/dist/lib/rich-text-editor/rich-text-editor.js +1 -1
  161. package/dist/lib/scroller/index.cjs +1 -1
  162. package/dist/lib/scroller/index.js +1 -1
  163. package/dist/lib/scroller/scroller.cjs +1 -1
  164. package/dist/lib/scroller/scroller.js +1 -1
  165. package/dist/lib/skeleton/skeleton.cjs +1 -1
  166. package/dist/lib/skeleton/skeleton.cjs.map +1 -1
  167. package/dist/lib/skeleton/skeleton.js +1 -0
  168. package/dist/lib/skeleton/skeleton.js.map +1 -1
  169. package/dist/lib/slider/index.cjs +1 -0
  170. package/dist/lib/slider/index.js +2 -0
  171. package/dist/lib/slider/slider.cjs +1 -0
  172. package/dist/lib/slider/slider.js +2 -0
  173. package/dist/lib/slider/utils.cjs +2 -0
  174. package/dist/lib/slider/utils.cjs.map +1 -0
  175. package/dist/lib/slider/utils.js +32 -0
  176. package/dist/lib/slider/utils.js.map +1 -0
  177. package/dist/lib/text-list/index.cjs +1 -1
  178. package/dist/lib/text-list/index.js +2 -2
  179. package/dist/lib/text-list/text-list-item.cjs +1 -1
  180. package/dist/lib/text-list/text-list-item.js +1 -1
  181. package/dist/lib/text-list/text-list.cjs +1 -1
  182. package/dist/lib/text-list/text-list.js +1 -1
  183. package/dist/lib/toast/index.cjs +1 -1
  184. package/dist/lib/toast/index.js +1 -1
  185. package/dist/lib/toast/toast.cjs +1 -1
  186. package/dist/lib/toast/toast.js +1 -1
  187. package/package.json +5 -5
  188. package/dist/Datepicker-CGFa1nGm.js.map +0 -1
  189. package/dist/Datepicker-DkGmnVc8.cjs +0 -2
  190. package/dist/Datepicker-DkGmnVc8.cjs.map +0 -1
  191. package/dist/EmojiPicker-BllVwJf4.js.map +0 -1
  192. package/dist/EmojiPicker-KO1yhODv.cjs +0 -2
  193. package/dist/EmojiPicker-KO1yhODv.cjs.map +0 -1
  194. package/dist/RichTextEditor-Cz2VXb7-.js.map +0 -1
  195. package/dist/RichTextEditor-EHgahp8r.cjs +0 -11
  196. package/dist/RichTextEditor-EHgahp8r.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"motion-text-constants.js","names":[],"sources":["../../../components/MotionText/MotionTextConstants.js"],"sourcesContent":["// Animation mode options\nexport const MOTION_TEXT_ANIMATION_MODES = [\n 'gradient-in',\n 'fade-in',\n 'slide-in',\n 'gradient-sweep',\n 'shimmer',\n 'none',\n];\n\n// Speed options\nexport const MOTION_TEXT_SPEEDS = ['100', '200', '300', '400', '500'];\n\n// Timing presets based on speed\nexport const MOTION_TEXT_TIMING_PRESETS = {\n 100: {\n characterDelay: 10,\n wordDelay: 15,\n duration: 300,\n },\n 200: {\n characterDelay: 20,\n wordDelay: 30,\n duration: 600,\n },\n 300: {\n characterDelay: 30,\n wordDelay: 50,\n duration: 1000,\n },\n 400: {\n characterDelay: 50,\n wordDelay: 100,\n duration: 1500,\n },\n 500: {\n characterDelay: 80,\n wordDelay: 180,\n duration: 2100,\n },\n};\n\nexport default {\n MOTION_TEXT_ANIMATION_MODES,\n MOTION_TEXT_SPEEDS,\n MOTION_TEXT_TIMING_PRESETS,\n};\n"],"mappings":";AACA,IAAa,IAA8B;CACzC;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAAqB;CAAC;CAAO;CAAO;CAAO;CAAO;CAAM,EAGxD,IAA6B;CACxC,KAAK;EACH,gBAAgB;EAChB,WAAW;EACX,UAAU;EACX;CACD,KAAK;EACH,gBAAgB;EAChB,WAAW;EACX,UAAU;EACX;CACD,KAAK;EACH,gBAAgB;EAChB,WAAW;EACX,UAAU;EACX;CACD,KAAK;EACH,gBAAgB;EAChB,WAAW;EACX,UAAU;EACX;CACD,KAAK;EACH,gBAAgB;EAChB,WAAW;EACX,UAAU;EACX;CACF,EAED,IAAe;CACb;CACA;CACA;CACD"}
1
+ {"version":3,"file":"motion-text-constants.js","names":[],"sources":["../../../components/MotionText/MotionTextConstants.js"],"sourcesContent":["// Animation mode options\nexport const MOTION_TEXT_ANIMATION_MODES = [\n 'gradient-in',\n 'fade-in',\n 'slide-in',\n 'slide-in-gradient',\n 'gradient-sweep',\n 'shimmer',\n 'none',\n];\n\n// Speed options\nexport const MOTION_TEXT_SPEEDS = ['100', '200', '300', '400', '500'];\n\n// Timing presets based on speed. `duration` relative to the 300 preset sets how much\n// every motion timing is scaled (300 plays the design spec as authored).\n// `characterDelay` and `wordDelay` are deprecated: unused since animation became word-level,\n// kept so code reading them doesn't break.\nexport const MOTION_TEXT_TIMING_PRESETS = {\n 100: { characterDelay: 10, wordDelay: 15, duration: 300 },\n 200: { characterDelay: 20, wordDelay: 30, duration: 600 },\n 300: { characterDelay: 30, wordDelay: 50, duration: 1000 },\n 400: { characterDelay: 50, wordDelay: 100, duration: 1500 },\n 500: { characterDelay: 80, wordDelay: 180, duration: 2100 },\n};\n\n// Per-word animation tracks in ms at speed 300, from the Motion Text design spec.\n// Word `i` starts at `delay + stagger * i` and runs for `duration`.\nexport const MOTION_TEXT_TRACKS = {\n // Word fades in (and rises, for slide modes)\n enter: { delay: 0, stagger: 60, duration: 300 },\n // Text color fades in over the gradient\n reveal: { delay: 250, stagger: 50, duration: 300 },\n // Word fades to the gradient, holds, then fades back over `fade`\n sweep: { delay: 350, stagger: 120, duration: 1400, fade: 250 },\n // A dimmed band sweeps left to right across the whole text at once (the original shimmer)\n shimmer: { delay: 0, stagger: 0, duration: 3000 },\n};\n\n// `loopHold` is the pause after the last word settles before a looped animation restarts.\n// `wholeText` modes animate the whole element, so the text and slot render as-is (markup and live\n// updates are kept) instead of being split into words.\n// With the six-word Figma sample it reproduces the 2000ms (reveal) and 2650ms (sweep) loops.\nexport const MOTION_TEXT_MODE_SETTINGS = {\n 'gradient-in': { tracks: ['enter', 'reveal'], gradient: true, loopHold: 1200 },\n 'fade-in': { tracks: ['enter'], gradient: false, loopHold: 1400 },\n 'slide-in': { tracks: ['enter'], gradient: false, loopHold: 1400 },\n 'slide-in-gradient': { tracks: ['enter', 'reveal'], gradient: true, loopHold: 1200 },\n 'gradient-sweep': { tracks: ['sweep'], gradient: true, loopHold: 300 },\n // Loops back to back, as the band starts and ends off the text\n shimmer: { tracks: ['shimmer'], gradient: false, loopHold: 0, wholeText: true },\n // Renders the text at rest, without animation\n none: { tracks: [], gradient: false, loopHold: 0 },\n};\n\nexport default {\n MOTION_TEXT_ANIMATION_MODES,\n MOTION_TEXT_SPEEDS,\n MOTION_TEXT_TIMING_PRESETS,\n MOTION_TEXT_TRACKS,\n MOTION_TEXT_MODE_SETTINGS,\n};\n"],"mappings":";AACA,IAAa,IAA8B;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAGY,IAAqB;CAAC;CAAO;CAAO;CAAO;CAAO;CAAM,EAMxD,IAA6B;CACxC,KAAK;EAAE,gBAAgB;EAAI,WAAW;EAAI,UAAU;EAAK;CACzD,KAAK;EAAE,gBAAgB;EAAI,WAAW;EAAI,UAAU;EAAK;CACzD,KAAK;EAAE,gBAAgB;EAAI,WAAW;EAAI,UAAU;EAAM;CAC1D,KAAK;EAAE,gBAAgB;EAAI,WAAW;EAAK,UAAU;EAAM;CAC3D,KAAK;EAAE,gBAAgB;EAAI,WAAW;EAAK,UAAU;EAAM;CAC5D,EAIY,IAAqB;CAEhC,OAAO;EAAE,OAAO;EAAG,SAAS;EAAI,UAAU;EAAK;CAE/C,QAAQ;EAAE,OAAO;EAAK,SAAS;EAAI,UAAU;EAAK;CAElD,OAAO;EAAE,OAAO;EAAK,SAAS;EAAK,UAAU;EAAM,MAAM;EAAK;CAE9D,SAAS;EAAE,OAAO;EAAG,SAAS;EAAG,UAAU;EAAM;CAClD,EAMY,IAA4B;CACvC,eAAe;EAAE,QAAQ,CAAC,SAAS,SAAS;EAAE,UAAU;EAAM,UAAU;EAAM;CAC9E,WAAW;EAAE,QAAQ,CAAC,QAAQ;EAAE,UAAU;EAAO,UAAU;EAAM;CACjE,YAAY;EAAE,QAAQ,CAAC,QAAQ;EAAE,UAAU;EAAO,UAAU;EAAM;CAClE,qBAAqB;EAAE,QAAQ,CAAC,SAAS,SAAS;EAAE,UAAU;EAAM,UAAU;EAAM;CACpF,kBAAkB;EAAE,QAAQ,CAAC,QAAQ;EAAE,UAAU;EAAM,UAAU;EAAK;CAEtE,SAAS;EAAE,QAAQ,CAAC,UAAU;EAAE,UAAU;EAAO,UAAU;EAAG,WAAW;EAAM;CAE/E,MAAM;EAAE,QAAQ,EAAE;EAAE,UAAU;EAAO,UAAU;EAAG;CACnD,EAED,IAAe;CACb;CACA;CACA;CACA;CACA;CACD"}
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../../chunk-Bmb41Sf3.cjs`);const e=require(`../../_plugin-vue_export-helper-D8jCH6HB.cjs`),t=require(`./motion-text-constants.cjs`);let n=require(`vue`);var r={name:`DtMotionText`,props:{text:{type:String,default:``},animationMode:{type:String,default:`gradient-in`,validator:e=>t.MOTION_TEXT_ANIMATION_MODES.includes(e)},speed:{type:[String,Number],default:300,validator:e=>t.MOTION_TEXT_SPEEDS.includes(String(e))},autoStart:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},respectsReducedMotion:{type:Boolean,default:!0},screenReaderText:{type:String,default:``}},emits:[`start`,`complete`,`progress`,`pause`,`resume`],data(){return{words:[],visibleWordCount:0,visibleCharsPerWord:[],isAnimating:!1,isPaused:!1,isLooped:!1,animationTimeouts:[],prefersReducedMotion:!1,animationKey:0}},computed:{timing(){return t.MOTION_TEXT_TIMING_PRESETS[String(this.speed)]},componentStyles(){return{"--d-motion-text-duration":`${this.timing.duration}ms`,"--d-motion-text-char-duration":`${this.timing.duration}ms`,"--d-motion-text-word-duration":`${this.timing.duration*2}ms`}},isStaticAnimationMode(){return this.animationMode===`gradient-sweep`||this.animationMode===`shimmer`},motionTextClasses(){return[`d-motion-text`,`d-motion-text--${this.animationMode}`,{"d-motion-text--animating":this.isAnimating,"d-motion-text--paused":this.isPaused,"d-motion-text--looped":this.isLooped}]}},watch:{text(){this.reset(),this.initializeContent()},loop:{handler(e){this.isLooped=e},immediate:!0}},mounted(){this.checkReducedMotion(),this.initializeContent()},beforeUnmount(){this.clearTimeouts()},methods:{processTextToChars(e){let t=[],n=(e,r=0)=>{if(e.nodeType===Node.TEXT_NODE){let n=e.textContent?.match(/\S+\s*/g)||[];return t.push(...n.map((e,t)=>({text:e,chars:e.split(``),index:r+t}))),r+n.length}else if(e.nodeType===Node.ELEMENT_NODE){let t=r;return Array.from(e.childNodes).forEach(e=>{t=n(e,t)}),t}return r};return n(e),t},processDirectText(e){return e?(e.match(/\S+\s*/g)||[]).map((e,t)=>({text:e,chars:e.split(``),index:t})):[]},checkReducedMotion(){typeof window<`u`&&window.matchMedia&&(this.prefersReducedMotion=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)},clearTimeouts(){this.animationTimeouts.forEach(e=>clearTimeout(e)),this.animationTimeouts=[]},start(){if(!this.isAnimating){if(this.isAnimating=!0,this.isPaused=!1,this.$emit(`start`),this.respectsReducedMotion&&this.prefersReducedMotion){this.showAllContent();return}if(this.animationMode===`none`){this.showAllContent();return}this.isStaticAnimationMode||this.showNextWord()}},pause(){!this.isAnimating||this.isPaused||(this.isPaused=!0,this.clearTimeouts(),this.$emit(`pause`))},resume(){this.isPaused&&(this.isPaused=!1,this.$emit(`resume`),this.showNextWord())},reset(){this.clearTimeouts(),this.isAnimating=!1,this.isPaused=!1,this.visibleWordCount=0,this.visibleCharsPerWord=Array(this.words.length).fill(0),this.animationKey++},skipToEnd(){this.showAllContent()},showAllContent(){this.visibleWordCount=this.words.length,this.visibleCharsPerWord=this.words.map(e=>e.chars.length),setTimeout(()=>{this.isAnimating=!1,this.$emit(`complete`)},0)},showNextWord(){if(this.isPaused||this.visibleWordCount>=this.words.length){this.visibleWordCount>=this.words.length&&this.completeAnimation();return}let e=setTimeout(()=>{this.visibleWordCount++,this.$emit(`progress`,{wordsComplete:this.visibleWordCount,totalWords:this.words.length,progress:this.visibleWordCount/this.words.length}),this.animateCharsForWord(this.visibleWordCount-1)},this.timing.wordDelay);this.animationTimeouts.push(e)},animateCharsForWord(e){if(this.isPaused||e>=this.words.length)return;this.visibleCharsPerWord[e]=0;let t=this.words[e].chars.length,n=()=>{if(this.isPaused||this.visibleCharsPerWord[e]>=t){this.visibleCharsPerWord[e]>=t&&this.showNextWord();return}this.visibleCharsPerWord[e]++;let r=setTimeout(n,this.timing.characterDelay);this.animationTimeouts.push(r)};n()},completeAnimation(){if(this.isAnimating=!1,this.clearTimeouts(),this.$emit(`complete`),this.loop){let e=setTimeout(()=>{this.reset(),this.$nextTick(()=>{this.start()})},500);this.animationTimeouts.push(e)}},initializeContent(){if(this.isStaticAnimationMode){this.autoStart&&this.$nextTick(()=>this.start());return}this.text?this.words=this.processDirectText(this.text):this.$refs.contentRef&&(this.words=this.processTextToChars(this.$refs.contentRef)),this.visibleCharsPerWord=Array(this.words.length).fill(0),this.visibleWordCount=0,this.autoStart&&this.words.length>0&&this.$nextTick(()=>this.start())}}},i=[`data-text-content`,`aria-live`,`aria-label`],a={key:0,class:`d-motion-text__sr-only`},o=[`aria-hidden`],s=[`data-text-content`],c={key:3,class:`d-motion-text__fallback`};function l(e,t,r,l,u,d){return(0,n.openBlock)(),(0,n.createElementBlock)(`span`,{ref:`contentRef`,class:(0,n.normalizeClass)(d.motionTextClasses),style:(0,n.normalizeStyle)(d.componentStyles),"data-text-content":d.isStaticAnimationMode?r.text:void 0,"aria-live":u.isAnimating?`polite`:`off`,"aria-label":r.screenReaderText||void 0},[r.screenReaderText?((0,n.openBlock)(),(0,n.createElementBlock)(`span`,a,(0,n.toDisplayString)(r.screenReaderText),1)):(0,n.createCommentVNode)(``,!0),d.isStaticAnimationMode?((0,n.openBlock)(),(0,n.createElementBlock)(n.Fragment,{key:1},[(0,n.createTextVNode)((0,n.toDisplayString)(r.text)+` `,1),r.text?(0,n.createCommentVNode)(``,!0):(0,n.renderSlot)(e.$slots,`default`,{key:0})],64)):((0,n.openBlock)(),(0,n.createElementBlock)(`span`,{key:u.animationKey,class:`d-motion-text__content`,"aria-hidden":u.isAnimating},[((0,n.openBlock)(!0),(0,n.createElementBlock)(n.Fragment,null,(0,n.renderList)(u.words,(e,t)=>((0,n.openBlock)(),(0,n.createBlock)(n.Transition,{key:`${u.animationKey}-${t}`,name:`d-motion-text-word-${r.animationMode}`},{default:(0,n.withCtx)(()=>[t<u.visibleWordCount?((0,n.openBlock)(),(0,n.createElementBlock)(`span`,{key:0,class:`d-motion-text__word`,"data-text-content":e.text,style:(0,n.normalizeStyle)({"--word-index":t})},[((0,n.openBlock)(!0),(0,n.createElementBlock)(n.Fragment,null,(0,n.renderList)(e.chars,(e,i)=>((0,n.openBlock)(),(0,n.createBlock)(n.Transition,{key:`${u.animationKey}-${t}-${i}`,name:`d-motion-text-char-${r.animationMode}`},{default:(0,n.withCtx)(()=>[i<u.visibleCharsPerWord[t]?((0,n.openBlock)(),(0,n.createElementBlock)(`span`,{key:0,class:`d-motion-text__char`,style:(0,n.normalizeStyle)({"--char-index":i,"--char-delay":`${i*d.timing.characterDelay}ms`})},(0,n.toDisplayString)(e),5)):(0,n.createCommentVNode)(``,!0)]),_:2},1032,[`name`]))),128))],12,s)):(0,n.createCommentVNode)(``,!0)]),_:2},1032,[`name`]))),128))],8,o)),!u.words.length&&!r.text&&!d.isStaticAnimationMode?((0,n.openBlock)(),(0,n.createElementBlock)(`span`,c,[(0,n.renderSlot)(e.$slots,`default`)])):(0,n.createCommentVNode)(``,!0)],14,i)}var u=e.t(r,[[`render`,l]]);exports.default=u;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../../chunk-Bmb41Sf3.cjs`);const e=require(`../../_plugin-vue_export-helper-D8jCH6HB.cjs`),t=require(`./motion-text-constants.cjs`),n=require(`./utils.cjs`);let r=require(`vue`);var i=t.MOTION_TEXT_TIMING_PRESETS[300],a={tracks:[],gradient:!1,loopHold:0},o={name:`DtMotionText`,props:{text:{type:String,default:``},animationMode:{type:String,default:`gradient-in`,validator:e=>t.MOTION_TEXT_ANIMATION_MODES.includes(e)},speed:{type:[String,Number],default:300,validator:e=>t.MOTION_TEXT_SPEEDS.includes(String(e))},autoStart:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},respectsReducedMotion:{type:Boolean,default:!0},screenReaderText:{type:String,default:``}},emits:[`start`,`complete`,`progress`,`pause`,`resume`],data(){return{words:n.splitWords(this.text),wordWidths:[],isRtl:!1,isAnimating:!1,isPaused:!1,isComplete:!1,isRestarting:!1,isLooped:!1,isUnmounted:!1,animationTimeouts:[],timelineStartedAt:0,timelineElapsed:0,prefersReducedMotion:!1,animationKey:0,cssIterations:1}},computed:{modeSettings(){return t.MOTION_TEXT_MODE_SETTINGS[this.animationMode]??a},isWholeText(){return!!this.modeSettings.wholeText},speedScale(){return(t.MOTION_TEXT_TIMING_PRESETS[String(this.speed)]??i).duration/i.duration},componentStyles(){let e={};return this.modeSettings.tracks.forEach(n=>{Object.entries(t.MOTION_TEXT_TRACKS[n]).forEach(([t,r])=>{e[`--d-motion-text-${n}-${t}`]=`${Math.round(r*this.speedScale)}ms`})}),e},wordStyles(){let e=this.modeSettings.gradient?n.getGradientSlices(this.wordWidths,this.isRtl):[];return this.words.map((t,n)=>{let r=e[n];return{"--d-motion-text-word-index":n,...r&&{"--d-motion-text-gradient-size":r.size,"--d-motion-text-gradient-position":r.position}}})},wordEndTimes(){return this.words.map((e,n)=>{let r=this.modeSettings.tracks.map(e=>{let{delay:r,stagger:i,duration:a}=t.MOTION_TEXT_TRACKS[e];return r+i*n+a});return Math.max(0,...r)*this.speedScale})},cycleDuration(){if(!this.isWholeText)return Math.max(0,...this.wordEndTimes);let e=this.modeSettings.tracks.map(e=>{let{delay:n,duration:r}=t.MOTION_TEXT_TRACKS[e];return n+r});return Math.max(0,...e)*this.speedScale*this.cssIterations},motionTextClasses(){return[`d-motion-text`,`d-motion-text--${this.animationMode}`,{"d-motion-text--animating":this.isAnimating,"d-motion-text--paused":this.isPaused,"d-motion-text--complete":this.isComplete,"d-motion-text--restarting":this.isRestarting,"d-motion-text--looped":this.isLooped,"d-motion-text--respects-reduced-motion":this.respectsReducedMotion}]}},watch:{text(){if(this.isWholeText){this.words=n.splitWords(this.text),this.isComplete&&this.autoStart&&!this.loop&&(this.reset(),this.$nextTick(()=>this.start()));return}if(this.reset(),this.text){this.initializeContent();return}this.words=[],this.$nextTick(()=>this.initializeContent())},animationMode(e,r){let i=!!t.MOTION_TEXT_MODE_SETTINGS[r]?.wholeText;if(!this.text&&i!==this.isWholeText){let e=this.isAnimating;this.reset(),this.words=[],this.$nextTick(()=>{this.words=n.splitWords(this.getSlotText()),this.wordWidths=[],e&&this.$nextTick(()=>this.start())});return}this.restartIfAnimating()},autoStart(e){e&&!this.isAnimating&&(this.isWholeText||this.words.length)&&this.$nextTick(()=>this.start())},speed(){this.restartIfAnimating()},loop:{handler(e){this.isLooped=e,this.isAnimating&&!this.isPaused&&(this.timelineElapsed=Date.now()-this.timelineStartedAt,this.clearTimeouts(),this.runTimeline())},immediate:!0}},mounted(){this.initWatchReducedMotion(),this.initializeContent(),document.fonts?.ready.then(()=>{!this.isUnmounted&&this.isAnimating&&this.measureWords()})},beforeUnmount(){this.isUnmounted=!0,this.clearTimeouts(),this.stopWatchingReducedMotion?.()},methods:{getSlotText(){return this.$refs.slotRef?.textContent||``},initWatchReducedMotion(){if(typeof window>`u`||!window.matchMedia)return;let e=window.matchMedia(`(prefers-reduced-motion: reduce)`),t=e=>{this.prefersReducedMotion=e.matches,e.matches&&this.respectsReducedMotion&&this.isAnimating&&this.skipToEnd()};this.prefersReducedMotion=e.matches,e.addEventListener?.(`change`,t),this.stopWatchingReducedMotion=()=>e.removeEventListener?.(`change`,t)},measureWords(){if(!this.modeSettings.gradient)return;let e=this.$refs.contentRef?.querySelectorAll(`.d-motion-text__word`)||[],t=Array.from(e,e=>e.getBoundingClientRect().width);this.isRtl=window.getComputedStyle(this.$el).direction===`rtl`,this.wordWidths=t.length===this.words.length&&t.every(e=>e>0)?t:this.words.map(e=>e.text.length)},clearTimeouts(){this.animationTimeouts.forEach(e=>clearTimeout(e)),this.animationTimeouts=[]},schedule(e,t){this.animationTimeouts.push(setTimeout(t,Math.max(0,e)))},runTimeline(){let e=this.timelineElapsed,t=this.words.length,n=this.cycleDuration;if(this.timelineStartedAt=Date.now()-e,(this.isWholeText?[]:this.wordEndTimes).forEach((n,r)=>{n<=e||this.schedule(n-e,()=>{this.$emit(`progress`,{wordsComplete:r+1,totalWords:t,progress:(r+1)/t})})}),n>e&&this.schedule(n-e,()=>this.completeAnimation()),this.loop){let t=n+this.modeSettings.loopHold*this.speedScale;this.schedule(t-e,()=>this.restartCycle())}else n<=e&&this.finishAnimation()},start(){if(!(this.isAnimating||this.isUnmounted)){if(this.clearTimeouts(),this.isAnimating=!0,this.isPaused=!1,this.isComplete=!1,this.$emit(`start`),this.respectsReducedMotion&&this.prefersReducedMotion){this.showAllContent();return}if(!this.modeSettings.tracks.length||!this.isWholeText&&!this.words.length){this.showAllContent();return}this.measureWords(),this.cssIterations=this.readCssIterations(),this.timelineElapsed=0,this.runTimeline()}},readCssIterations(){if(!this.isWholeText||this.loop)return 1;let e=parseFloat(window.getComputedStyle(this.$el).animationIterationCount);return Number.isFinite(e)&&e>1?e:1},pause(){!this.isAnimating||this.isPaused||(this.timelineElapsed=Date.now()-this.timelineStartedAt,this.clearTimeouts(),this.isPaused=!0,this.$emit(`pause`))},resume(){this.isPaused&&(this.isPaused=!1,this.$emit(`resume`),this.runTimeline())},reset(){this.clearTimeouts(),this.isAnimating=!1,this.isPaused=!1,this.isComplete=!1,this.timelineElapsed=0,this.animationKey++,this.replayAnimations()},skipToEnd(){this.showAllContent()},showAllContent(){this.finishAnimation(),this.isPaused=!1,this.schedule(0,()=>this.$emit(`complete`))},finishAnimation(){this.clearTimeouts(),this.isAnimating=!1,this.isComplete=!0},restartIfAnimating(){this.isAnimating&&(this.reset(),this.$nextTick(()=>this.start()))},completeAnimation(){this.$emit(`complete`),this.loop||this.finishAnimation()},replayAnimations(e){this.isRestarting=!0,this.$nextTick(()=>{this.$el?.getBoundingClientRect?.(),this.isRestarting=!1,e?.()})},restartCycle(){this.isUnmounted||(this.clearTimeouts(),this.replayAnimations(()=>{this.measureWords(),this.timelineElapsed=0,this.$emit(`start`),this.runTimeline()}))},initializeContent(){this.words=n.splitWords(this.text||this.getSlotText()),this.wordWidths=[],this.autoStart&&(this.isWholeText||this.words.length>0)&&this.$nextTick(()=>this.start())}}},s=[`aria-live`,`aria-label`],c={key:0,"data-qa":`dt-motion-text-sr-only`,class:`d-motion-text__sr-only`},l=[`aria-hidden`],u=[`aria-hidden`],d={key:3,ref:`slotRef`,class:`d-motion-text__fallback`};function f(e,t,n,i,a,o){return(0,r.openBlock)(),(0,r.createElementBlock)(`span`,{"data-qa":`dt-motion-text`,class:(0,r.normalizeClass)(o.motionTextClasses),style:(0,r.normalizeStyle)(o.componentStyles),"aria-live":a.isAnimating?`polite`:`off`,"aria-label":n.screenReaderText||void 0},[n.screenReaderText?((0,r.openBlock)(),(0,r.createElementBlock)(`span`,c,(0,r.toDisplayString)(n.screenReaderText),1)):(0,r.createCommentVNode)(``,!0),o.isWholeText?((0,r.openBlock)(),(0,r.createElementBlock)(`span`,{key:1,ref:`slotRef`,"data-qa":`dt-motion-text-content`,class:`d-motion-text__content`,"aria-hidden":n.screenReaderText?`true`:void 0},[(0,r.createTextVNode)((0,r.toDisplayString)(n.text),1),n.text?(0,r.createCommentVNode)(``,!0):(0,r.renderSlot)(e.$slots,`default`,{key:0})],8,l)):a.words.length?((0,r.openBlock)(),(0,r.createElementBlock)(`span`,{ref:`contentRef`,key:a.animationKey,"data-qa":`dt-motion-text-content`,class:`d-motion-text__content`,"aria-hidden":n.screenReaderText?`true`:void 0},[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(a.words,(e,t)=>((0,r.openBlock)(),(0,r.createElementBlock)(r.Fragment,{key:`${a.animationKey}-${t}`},[(0,r.createElementVNode)(`span`,{"data-qa":`dt-motion-text-word`,class:`d-motion-text__word`,style:(0,r.normalizeStyle)(o.wordStyles[t])},(0,r.toDisplayString)(e.text),5),(0,r.createTextVNode)((0,r.toDisplayString)(e.space),1)],64))),128))],8,u)):((0,r.openBlock)(),(0,r.createElementBlock)(`span`,d,[(0,r.renderSlot)(e.$slots,`default`)],512))],14,s)}var p=e.t(o,[[`render`,f]]);exports.default=p;
2
2
  //# sourceMappingURL=motion-text.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"motion-text.cjs","names":[],"sources":["../../../components/MotionText/MotionText.vue"],"sourcesContent":["<template>\n <span\n ref=\"contentRef\"\n :class=\"motionTextClasses\"\n :style=\"componentStyles\"\n :data-text-content=\"isStaticAnimationMode ? text : undefined\"\n :aria-live=\"isAnimating ? 'polite' : 'off'\"\n :aria-label=\"screenReaderText || undefined\"\n >\n <!-- Screen reader content -->\n <span\n v-if=\"screenReaderText\"\n class=\"d-motion-text__sr-only\"\n >\n {{ screenReaderText }}\n </span>\n\n <!-- Gradient-sweep and shimmer modes: Simple static text with gradient animation -->\n <template v-if=\"isStaticAnimationMode\">\n {{ text }}\n <slot v-if=\"!text\" />\n </template>\n\n <!-- Character-by-character animated content for other modes -->\n <span\n v-else\n :key=\"animationKey\"\n class=\"d-motion-text__content\"\n :aria-hidden=\"isAnimating\"\n >\n <template\n v-for=\"(word, wordIdx) in words\"\n :key=\"`${animationKey}-${wordIdx}`\"\n >\n <Transition\n :name=\"`d-motion-text-word-${animationMode}`\"\n >\n <span\n v-if=\"wordIdx < visibleWordCount\"\n class=\"d-motion-text__word\"\n :data-text-content=\"word.text\"\n :style=\"{ '--word-index': wordIdx }\"\n >\n <template\n v-for=\"(char, charIdx) in word.chars\"\n :key=\"`${animationKey}-${wordIdx}-${charIdx}`\"\n >\n <Transition\n :name=\"`d-motion-text-char-${animationMode}`\"\n >\n <span\n v-if=\"charIdx < visibleCharsPerWord[wordIdx]\"\n class=\"d-motion-text__char\"\n :style=\"{\n '--char-index': charIdx,\n '--char-delay': `${charIdx * timing.characterDelay}ms`,\n }\"\n >{{ char }}</span>\n </Transition>\n </template>\n </span>\n </Transition>\n </template>\n </span>\n\n <!-- Fallback slot content -->\n <span\n v-if=\"!words.length && !text && !isStaticAnimationMode\"\n class=\"d-motion-text__fallback\"\n >\n <slot />\n </span>\n </span>\n</template>\n\n<script>\nimport { MOTION_TEXT_ANIMATION_MODES, MOTION_TEXT_SPEEDS, MOTION_TEXT_TIMING_PRESETS } from './MotionTextConstants';\n\nexport default {\n name: 'DtMotionText',\n\n props: {\n /**\n * The text content to animate.\n * @type {string}\n */\n text: {\n type: String,\n default: '',\n },\n\n /**\n * The animation mode to use for the text reveal.\n * @values gradient-in, fade-in, slide-in, gradient-sweep, shimmer, none\n */\n animationMode: {\n type: String,\n default: 'gradient-in',\n validator: (value) => MOTION_TEXT_ANIMATION_MODES.includes(value),\n },\n\n /**\n * Animation speed.\n * @values 100, 200, 300, 400, 500\n */\n speed: {\n type: [String, Number],\n default: 300,\n validator: (value) => MOTION_TEXT_SPEEDS.includes(String(value)),\n },\n\n /**\n * Whether to start animation automatically when component is mounted.\n * @values true, false\n */\n autoStart: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether to loop the animation continuously.\n * @values true, false\n */\n loop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Whether to respect the user's prefers-reduced-motion system setting.\n * @values true, false\n */\n respectsReducedMotion: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Alternative text for screen readers. If provided, this will be announced\n * instead of the animated text.\n * @type {string}\n */\n screenReaderText: {\n type: String,\n default: '',\n },\n },\n\n emits: [\n /**\n * Emitted when the animation starts.\n * @event start\n */\n 'start',\n\n /**\n * Emitted when the animation completes.\n * @event complete\n */\n 'complete',\n\n /**\n * Emitted during animation progress.\n * @event progress\n * @type {{ wordsComplete: number, totalWords: number, progress: number }}\n */\n 'progress',\n\n /**\n * Emitted when the animation is paused.\n * @event pause\n */\n 'pause',\n\n /**\n * Emitted when the animation resumes.\n * @event resume\n */\n 'resume',\n ],\n\n data () {\n return {\n words: [],\n visibleWordCount: 0,\n visibleCharsPerWord: [],\n isAnimating: false,\n isPaused: false,\n isLooped: false,\n animationTimeouts: [],\n prefersReducedMotion: false,\n animationKey: 0,\n };\n },\n\n computed: {\n /**\n * Get timing preset based on speed prop\n */\n timing () {\n return MOTION_TEXT_TIMING_PRESETS[String(this.speed)];\n },\n\n /**\n * Computed styles with timing CSS variables\n */\n componentStyles () {\n return {\n '--d-motion-text-duration': `${this.timing.duration}ms`,\n '--d-motion-text-char-duration': `${this.timing.duration}ms`,\n '--d-motion-text-word-duration': `${this.timing.duration * 2}ms`,\n };\n },\n\n /**\n * Check if current animation mode is static (gradient-sweep or shimmer)\n */\n isStaticAnimationMode () {\n return this.animationMode === 'gradient-sweep' || this.animationMode === 'shimmer';\n },\n\n /**\n * Computed classes for the motion text element\n */\n motionTextClasses () {\n return [\n 'd-motion-text',\n `d-motion-text--${this.animationMode}`,\n {\n 'd-motion-text--animating': this.isAnimating,\n 'd-motion-text--paused': this.isPaused,\n 'd-motion-text--looped': this.isLooped,\n },\n ];\n },\n },\n\n watch: {\n text () {\n this.reset();\n this.initializeContent();\n },\n\n loop: {\n handler (newVal) {\n this.isLooped = newVal;\n },\n\n immediate: true,\n },\n },\n\n mounted () {\n this.checkReducedMotion();\n this.initializeContent();\n },\n\n beforeUnmount () {\n this.clearTimeouts();\n },\n\n methods: {\n /**\n * Self-contained text processing from DOM nodes\n */\n processTextToChars (node) {\n const words = [];\n\n const processNode = (node, index = 0) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const matches = node.textContent?.match(/\\S+\\s*/g) || [];\n words.push(...matches.map((text, i) => ({\n text,\n chars: text.split(''),\n index: index + i,\n })));\n return index + matches.length;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n let currentIdx = index;\n Array.from(node.childNodes).forEach(child => {\n currentIdx = processNode(child, currentIdx);\n });\n return currentIdx;\n }\n return index;\n };\n\n processNode(node);\n return words;\n },\n\n /**\n * Process direct text prop into word/character data\n */\n processDirectText (text) {\n if (!text) return [];\n\n const matches = text.match(/\\S+\\s*/g) || [];\n return matches.map((wordText, i) => ({\n text: wordText,\n chars: wordText.split(''),\n index: i,\n }));\n },\n\n /**\n * Check for reduced motion preference\n */\n checkReducedMotion () {\n if (typeof window !== 'undefined' && window.matchMedia) {\n this.prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n },\n\n /**\n * Clear all animation timeouts\n */\n clearTimeouts () {\n this.animationTimeouts.forEach(timeout => clearTimeout(timeout));\n this.animationTimeouts = [];\n },\n\n /**\n * Start the animation\n * @public\n */\n start () {\n if (this.isAnimating) return;\n\n this.isAnimating = true;\n this.isPaused = false;\n this.$emit('start');\n\n // Skip animation if reduced motion is preferred and enabled\n if (this.respectsReducedMotion && this.prefersReducedMotion) {\n this.showAllContent();\n return;\n }\n\n if (this.animationMode === 'none') {\n this.showAllContent();\n return;\n }\n\n // For gradient-sweep and shimmer modes, just mark as animating (CSS handles the animation)\n if (this.isStaticAnimationMode) {\n return;\n }\n\n // Start the word-by-word animation for \"-in\" modes\n this.showNextWord();\n },\n\n /**\n * Pause the animation\n * @public\n */\n pause () {\n if (!this.isAnimating || this.isPaused) return;\n\n this.isPaused = true;\n this.clearTimeouts();\n this.$emit('pause');\n },\n\n /**\n * Resume the animation\n * @public\n */\n resume () {\n if (!this.isPaused) return;\n\n this.isPaused = false;\n this.$emit('resume');\n this.showNextWord();\n },\n\n /**\n * Reset the animation to initial state\n * @public\n */\n reset () {\n this.clearTimeouts();\n this.isAnimating = false;\n this.isPaused = false;\n this.visibleWordCount = 0;\n this.visibleCharsPerWord = Array(this.words.length).fill(0);\n this.animationKey++;\n },\n\n /**\n * Skip to the end of the animation\n * @public\n */\n skipToEnd () {\n this.showAllContent();\n },\n\n /**\n * Show all content immediately\n */\n showAllContent () {\n this.visibleWordCount = this.words.length;\n this.visibleCharsPerWord = this.words.map(word => word.chars.length);\n setTimeout(() => {\n this.isAnimating = false;\n this.$emit('complete');\n }, 0);\n },\n\n /**\n * Show next word in sequence\n */\n showNextWord () {\n if (this.isPaused || this.visibleWordCount >= this.words.length) {\n if (this.visibleWordCount >= this.words.length) {\n this.completeAnimation();\n }\n return;\n }\n\n const timeout = setTimeout(() => {\n this.visibleWordCount++;\n this.$emit('progress', {\n wordsComplete: this.visibleWordCount,\n totalWords: this.words.length,\n progress: this.visibleWordCount / this.words.length,\n });\n\n this.animateCharsForWord(this.visibleWordCount - 1);\n }, this.timing.wordDelay);\n\n this.animationTimeouts.push(timeout);\n },\n\n /**\n * Animate characters for a specific word\n */\n animateCharsForWord (wordIdx) {\n if (this.isPaused || wordIdx >= this.words.length) return;\n\n this.visibleCharsPerWord[wordIdx] = 0;\n const chars = this.words[wordIdx].chars.length;\n\n const revealChar = () => {\n if (this.isPaused || this.visibleCharsPerWord[wordIdx] >= chars) {\n if (this.visibleCharsPerWord[wordIdx] >= chars) {\n this.showNextWord();\n }\n return;\n }\n\n this.visibleCharsPerWord[wordIdx]++;\n const timeout = setTimeout(revealChar, this.timing.characterDelay);\n this.animationTimeouts.push(timeout);\n };\n\n revealChar();\n },\n\n /**\n * Complete the animation\n */\n completeAnimation () {\n this.isAnimating = false;\n this.clearTimeouts();\n\n this.$emit('complete');\n\n if (this.loop) {\n const timeout = setTimeout(() => {\n this.reset();\n this.$nextTick(() => {\n this.start();\n });\n }, 500);\n\n this.animationTimeouts.push(timeout);\n }\n },\n\n /**\n * Initialize content based on text prop or slot content\n */\n initializeContent () {\n // For gradient-sweep and shimmer modes, skip word/character processing\n if (this.isStaticAnimationMode) {\n if (this.autoStart) {\n this.$nextTick(() => this.start());\n }\n return;\n }\n\n if (this.text) {\n this.words = this.processDirectText(this.text);\n } else if (this.$refs.contentRef) {\n this.words = this.processTextToChars(this.$refs.contentRef);\n }\n\n this.visibleCharsPerWord = Array(this.words.length).fill(0);\n this.visibleWordCount = 0;\n\n if (this.autoStart && this.words.length > 0) {\n this.$nextTick(() => this.start());\n }\n },\n },\n};\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"motion-text.cjs","names":[],"sources":["../../../components/MotionText/MotionText.vue"],"sourcesContent":["<template>\n <span\n data-qa=\"dt-motion-text\"\n :class=\"motionTextClasses\"\n :style=\"componentStyles\"\n :aria-live=\"isAnimating ? 'polite' : 'off'\"\n :aria-label=\"screenReaderText || undefined\"\n >\n <!-- Screen reader content -->\n <span\n v-if=\"screenReaderText\"\n data-qa=\"dt-motion-text-sr-only\"\n class=\"d-motion-text__sr-only\"\n >\n {{ screenReaderText }}\n </span>\n\n <!-- Whole-text modes animate the root, so the text and slot render as-is and stay live -->\n <span\n v-if=\"isWholeText\"\n ref=\"slotRef\"\n data-qa=\"dt-motion-text-content\"\n class=\"d-motion-text__content\"\n :aria-hidden=\"screenReaderText ? 'true' : undefined\"\n >{{ text }}<slot v-if=\"!text\" /></span>\n\n <!-- Word-by-word animated content -->\n <span\n v-else-if=\"words.length\"\n ref=\"contentRef\"\n :key=\"animationKey\"\n data-qa=\"dt-motion-text-content\"\n class=\"d-motion-text__content\"\n :aria-hidden=\"screenReaderText ? 'true' : undefined\"\n >\n <template\n v-for=\"(word, wordIdx) in words\"\n :key=\"`${animationKey}-${wordIdx}`\"\n >\n <span\n data-qa=\"dt-motion-text-word\"\n class=\"d-motion-text__word\"\n :style=\"wordStyles[wordIdx]\"\n >{{ word.text }}</span>{{ word.space }}\n </template>\n </span>\n\n <!-- Slot content, rendered until its text has been split into words -->\n <span\n v-else\n ref=\"slotRef\"\n class=\"d-motion-text__fallback\"\n >\n <slot />\n </span>\n </span>\n</template>\n\n\n<script>\nimport {\n MOTION_TEXT_ANIMATION_MODES,\n MOTION_TEXT_MODE_SETTINGS,\n MOTION_TEXT_SPEEDS,\n MOTION_TEXT_TIMING_PRESETS,\n MOTION_TEXT_TRACKS,\n} from './MotionTextConstants';\nimport { getGradientSlices, splitWords } from './utils';\n\nconst DEFAULT_PRESET = MOTION_TEXT_TIMING_PRESETS['300'];\n// Unsupported modes render the text at rest, like 'none'\nconst RESTING_SETTINGS = { tracks: [], gradient: false, loopHold: 0 };\n\nexport default {\n name: 'DtMotionText',\n\n props: {\n /**\n * The text content to animate.\n * @type {string}\n */\n text: {\n type: String,\n default: '',\n },\n\n /**\n * The animation mode to use for the text reveal. `none` renders the text without animation.\n * @values gradient-in, fade-in, slide-in, slide-in-gradient, gradient-sweep, shimmer, none\n */\n animationMode: {\n type: String,\n default: 'gradient-in',\n validator: (value) => MOTION_TEXT_ANIMATION_MODES.includes(value),\n },\n\n /**\n * Animation speed. 300 plays the motion spec as designed; lower values are faster.\n * @values 100, 200, 300, 400, 500\n */\n speed: {\n type: [String, Number],\n default: 300,\n validator: (value) => MOTION_TEXT_SPEEDS.includes(String(value)),\n },\n\n /**\n * Whether to start animation automatically when component is mounted.\n * @values true, false\n */\n autoStart: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether to loop the animation continuously.\n * @values true, false\n */\n loop: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Whether to respect the user's prefers-reduced-motion system setting.\n * @values true, false\n */\n respectsReducedMotion: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Alternative text for screen readers. If provided, this will be announced\n * instead of the animated text.\n * @type {string}\n */\n screenReaderText: {\n type: String,\n default: '',\n },\n },\n\n emits: [\n /**\n * Emitted when the animation starts, and at the start of each looped cycle.\n * @event start\n */\n 'start',\n\n /**\n * Emitted when the animation completes, and at the end of each looped cycle.\n * @event complete\n */\n 'complete',\n\n /**\n * Emitted as each word finishes animating.\n * @event progress\n * @type {{ wordsComplete: number, totalWords: number, progress: number }}\n */\n 'progress',\n\n /**\n * Emitted when the animation is paused.\n * @event pause\n */\n 'pause',\n\n /**\n * Emitted when the animation resumes.\n * @event resume\n */\n 'resume',\n ],\n\n data () {\n return {\n words: splitWords(this.text),\n wordWidths: [],\n isRtl: false,\n isAnimating: false,\n isPaused: false,\n isComplete: false,\n isRestarting: false,\n isLooped: false,\n isUnmounted: false,\n animationTimeouts: [],\n timelineStartedAt: 0,\n timelineElapsed: 0,\n prefersReducedMotion: false,\n animationKey: 0,\n cssIterations: 1,\n };\n },\n\n computed: {\n modeSettings () {\n return MOTION_TEXT_MODE_SETTINGS[this.animationMode] ?? RESTING_SETTINGS;\n },\n\n isWholeText () {\n return Boolean(this.modeSettings.wholeText);\n },\n\n /**\n * Multiplier applied to every motion timing for the current speed.\n */\n speedScale () {\n const preset = MOTION_TEXT_TIMING_PRESETS[String(this.speed)] ?? DEFAULT_PRESET;\n return preset.duration / DEFAULT_PRESET.duration;\n },\n\n /**\n * Track timings for the current mode as CSS variables, e.g. --d-motion-text-enter-stagger\n */\n componentStyles () {\n const styles = {};\n this.modeSettings.tracks.forEach(track => {\n Object.entries(MOTION_TEXT_TRACKS[track]).forEach(([key, value]) => {\n styles[`--d-motion-text-${track}-${key}`] = `${Math.round(value * this.speedScale)}ms`;\n });\n });\n return styles;\n },\n\n /**\n * Per-word index (drives the stagger) and, in gradient modes, the slice of the shared gradient\n * each word shows so it reads as one continuous gradient across the text.\n */\n wordStyles () {\n const slices = this.modeSettings.gradient ? getGradientSlices(this.wordWidths, this.isRtl) : [];\n\n return this.words.map((word, index) => {\n const slice = slices[index];\n return {\n '--d-motion-text-word-index': index,\n ...(slice && {\n '--d-motion-text-gradient-size': slice.size,\n '--d-motion-text-gradient-position': slice.position,\n }),\n };\n });\n },\n\n /**\n * Time (ms) at which each word finishes its last track\n */\n wordEndTimes () {\n return this.words.map((word, index) => {\n const ends = this.modeSettings.tracks.map(track => {\n const { delay, stagger, duration } = MOTION_TEXT_TRACKS[track];\n return delay + stagger * index + duration;\n });\n return Math.max(0, ...ends) * this.speedScale;\n });\n },\n\n /**\n * Time (ms) at which one cycle of the animation ends\n */\n cycleDuration () {\n if (!this.isWholeText) return Math.max(0, ...this.wordEndTimes);\n\n const ends = this.modeSettings.tracks.map(track => {\n const { delay, duration } = MOTION_TEXT_TRACKS[track];\n return delay + duration;\n });\n return Math.max(0, ...ends) * this.speedScale * this.cssIterations;\n },\n\n motionTextClasses () {\n return [\n 'd-motion-text',\n `d-motion-text--${this.animationMode}`,\n {\n 'd-motion-text--animating': this.isAnimating,\n 'd-motion-text--paused': this.isPaused,\n 'd-motion-text--complete': this.isComplete,\n 'd-motion-text--restarting': this.isRestarting,\n 'd-motion-text--looped': this.isLooped,\n 'd-motion-text--respects-reduced-motion': this.respectsReducedMotion,\n },\n ];\n },\n },\n\n watch: {\n text () {\n // Whole-text modes render the text live and keep animating, as they always have\n if (this.isWholeText) {\n this.words = splitWords(this.text);\n\n // A finished single play runs again for the new text; a loop stopped with skipToEnd() stays at rest\n if (this.isComplete && this.autoStart && !this.loop) {\n this.reset();\n this.$nextTick(() => this.start());\n }\n return;\n }\n\n this.reset();\n\n if (this.text) {\n this.initializeContent();\n return;\n }\n\n // Slot content only renders once the words are cleared, so read it on the next tick\n this.words = [];\n this.$nextTick(() => this.initializeContent());\n },\n\n animationMode (mode, oldMode) {\n const wasWholeText = Boolean(MOTION_TEXT_MODE_SETTINGS[oldMode]?.wholeText);\n\n // Whole-text modes render the slot live, so read it again when switching to or from word mode\n if (!this.text && wasWholeText !== this.isWholeText) {\n const wasAnimating = this.isAnimating;\n this.reset();\n this.words = [];\n this.$nextTick(() => {\n this.words = splitWords(this.getSlotText());\n this.wordWidths = [];\n if (wasAnimating) this.$nextTick(() => this.start());\n });\n return;\n }\n\n this.restartIfAnimating();\n },\n\n autoStart (value) {\n if (value && !this.isAnimating && (this.isWholeText || this.words.length)) {\n this.$nextTick(() => this.start());\n }\n },\n\n speed () {\n this.restartIfAnimating();\n },\n\n loop: {\n handler (newVal) {\n this.isLooped = newVal;\n\n // Reschedule so the current cycle ends (or restarts) according to the new value\n if (this.isAnimating && !this.isPaused) {\n this.timelineElapsed = Date.now() - this.timelineStartedAt;\n this.clearTimeouts();\n this.runTimeline();\n }\n },\n\n immediate: true,\n },\n },\n\n mounted () {\n this.initWatchReducedMotion();\n this.initializeContent();\n\n // Word widths change once web fonts load, which would misalign the gradient slices\n document.fonts?.ready.then(() => {\n if (!this.isUnmounted && this.isAnimating) this.measureWords();\n });\n },\n\n beforeUnmount () {\n this.isUnmounted = true;\n this.clearTimeouts();\n this.stopWatchingReducedMotion?.();\n },\n\n methods: {\n /**\n * Collect the text of slot content, ignoring markup\n */\n getSlotText () {\n return this.$refs.slotRef?.textContent || '';\n },\n\n /**\n * Track the reduced motion preference, finishing any running animation if it turns on\n */\n initWatchReducedMotion () {\n if (typeof window === 'undefined' || !window.matchMedia) return;\n\n const query = window.matchMedia('(prefers-reduced-motion: reduce)');\n const onChange = (event) => {\n this.prefersReducedMotion = event.matches;\n if (event.matches && this.respectsReducedMotion && this.isAnimating) this.skipToEnd();\n };\n\n this.prefersReducedMotion = query.matches;\n query.addEventListener?.('change', onChange);\n this.stopWatchingReducedMotion = () => query.removeEventListener?.('change', onChange);\n },\n\n /**\n * Measure rendered word widths so each word can show its slice of the gradient.\n * Falls back to character counts when layout is unavailable (e.g. not yet rendered).\n */\n measureWords () {\n if (!this.modeSettings.gradient) return;\n\n const wordEls = this.$refs.contentRef?.querySelectorAll('.d-motion-text__word') || [];\n const widths = Array.from(wordEls, el => el.getBoundingClientRect().width);\n\n this.isRtl = window.getComputedStyle(this.$el).direction === 'rtl';\n this.wordWidths = widths.length === this.words.length && widths.every(width => width > 0)\n ? widths\n : this.words.map(word => word.text.length);\n },\n\n /**\n * Clear all animation timeouts\n */\n clearTimeouts () {\n this.animationTimeouts.forEach(timeout => clearTimeout(timeout));\n this.animationTimeouts = [];\n },\n\n schedule (delay, callback) {\n this.animationTimeouts.push(setTimeout(callback, Math.max(0, delay)));\n },\n\n /**\n * Schedule progress, completion and (when looping) restart events for the remainder\n * of the current cycle. CSS runs the animation itself; this keeps events in step with it.\n */\n runTimeline () {\n const elapsed = this.timelineElapsed;\n const totalWords = this.words.length;\n const cycleEnd = this.cycleDuration;\n\n this.timelineStartedAt = Date.now() - elapsed;\n\n // Whole-text modes have no per-word progress\n const wordEnds = this.isWholeText ? [] : this.wordEndTimes;\n wordEnds.forEach((end, index) => {\n if (end <= elapsed) return;\n this.schedule(end - elapsed, () => {\n this.$emit('progress', {\n wordsComplete: index + 1,\n totalWords,\n progress: (index + 1) / totalWords,\n });\n });\n });\n\n if (cycleEnd > elapsed) {\n this.schedule(cycleEnd - elapsed, () => this.completeAnimation());\n }\n\n if (this.loop) {\n const restartAt = cycleEnd + this.modeSettings.loopHold * this.speedScale;\n this.schedule(restartAt - elapsed, () => this.restartCycle());\n } else if (cycleEnd <= elapsed) {\n // The cycle already ended while looping (e.g. loop turned off during the hold)\n this.finishAnimation();\n }\n },\n\n /**\n * Start the animation\n * @public\n */\n start () {\n if (this.isAnimating || this.isUnmounted) return;\n\n this.clearTimeouts();\n this.isAnimating = true;\n this.isPaused = false;\n this.isComplete = false;\n this.$emit('start');\n\n // Skip animation if reduced motion is preferred and enabled\n if (this.respectsReducedMotion && this.prefersReducedMotion) {\n this.showAllContent();\n return;\n }\n\n if (!this.modeSettings.tracks.length || (!this.isWholeText && !this.words.length)) {\n this.showAllContent();\n return;\n }\n\n this.measureWords();\n this.cssIterations = this.readCssIterations();\n this.timelineElapsed = 0;\n this.runTimeline();\n },\n\n /**\n * Whole-text animations honor a consumer's animation-iteration-count override (e.g. 2 sweeps)\n */\n readCssIterations () {\n if (!this.isWholeText || this.loop) return 1;\n\n const count = parseFloat(window.getComputedStyle(this.$el).animationIterationCount);\n return Number.isFinite(count) && count > 1 ? count : 1;\n },\n\n /**\n * Pause the animation\n * @public\n */\n pause () {\n if (!this.isAnimating || this.isPaused) return;\n\n this.timelineElapsed = Date.now() - this.timelineStartedAt;\n this.clearTimeouts();\n this.isPaused = true;\n this.$emit('pause');\n },\n\n /**\n * Resume the animation\n * @public\n */\n resume () {\n if (!this.isPaused) return;\n\n this.isPaused = false;\n this.$emit('resume');\n this.runTimeline();\n },\n\n /**\n * Reset the animation to initial state\n * @public\n */\n reset () {\n this.clearTimeouts();\n this.isAnimating = false;\n this.isPaused = false;\n this.isComplete = false;\n this.timelineElapsed = 0;\n this.animationKey++;\n // Whole-text modes animate the root, which re-keying the words doesn't reset\n this.replayAnimations();\n },\n\n /**\n * Skip to the end of the animation\n * @public\n */\n skipToEnd () {\n this.showAllContent();\n },\n\n /**\n * Show all content immediately in its resting state\n */\n showAllContent () {\n this.finishAnimation();\n this.isPaused = false;\n this.schedule(0, () => this.$emit('complete'));\n },\n\n finishAnimation () {\n this.clearTimeouts();\n this.isAnimating = false;\n this.isComplete = true;\n },\n\n restartIfAnimating () {\n if (!this.isAnimating) return;\n\n this.reset();\n this.$nextTick(() => this.start());\n },\n\n /**\n * End of a cycle. Looped animations keep animating through the hold before restarting.\n */\n completeAnimation () {\n this.$emit('complete');\n if (!this.loop) this.finishAnimation();\n },\n\n /**\n * Drop the CSS animations for one style pass so they replay from their first frame on the same\n * elements, keeping text selection and not re-inserting anything into the aria-live region.\n */\n replayAnimations (callback) {\n this.isRestarting = true;\n\n this.$nextTick(() => {\n // Flush styles while the animations are removed\n this.$el?.getBoundingClientRect?.();\n this.isRestarting = false;\n callback?.();\n });\n },\n\n /**\n * Restart a looped animation: everything returns to its starting state at once\n */\n restartCycle () {\n if (this.isUnmounted) return;\n\n this.clearTimeouts();\n this.replayAnimations(() => {\n this.measureWords();\n this.timelineElapsed = 0;\n this.$emit('start');\n this.runTimeline();\n });\n },\n\n /**\n * Initialize content based on text prop or slot content\n */\n initializeContent () {\n this.words = splitWords(this.text || this.getSlotText());\n this.wordWidths = [];\n\n // Whole-text modes start even while empty, e.g. a slot that streams its content in\n if (this.autoStart && (this.isWholeText || this.words.length > 0)) {\n this.$nextTick(() => this.start());\n }\n },\n },\n};\n</script>\n"],"mappings":"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"}
@@ -1,8 +1,13 @@
1
1
  import { t as e } from "../../_plugin-vue_export-helper-BTgDAbhb.js";
2
- import { MOTION_TEXT_ANIMATION_MODES as t, MOTION_TEXT_SPEEDS as n, MOTION_TEXT_TIMING_PRESETS as r } from "./motion-text-constants.js";
3
- import { Fragment as i, Transition as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createTextVNode as l, normalizeClass as u, normalizeStyle as d, openBlock as f, renderList as p, renderSlot as m, toDisplayString as h, withCtx as g } from "vue";
2
+ import { MOTION_TEXT_ANIMATION_MODES as t, MOTION_TEXT_MODE_SETTINGS as n, MOTION_TEXT_SPEEDS as r, MOTION_TEXT_TIMING_PRESETS as i, MOTION_TEXT_TRACKS as a } from "./motion-text-constants.js";
3
+ import { getGradientSlices as o, splitWords as s } from "./utils.js";
4
+ import { Fragment as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, normalizeClass as p, normalizeStyle as m, openBlock as h, renderList as g, renderSlot as _, toDisplayString as v } from "vue";
4
5
  //#region components/MotionText/MotionText.vue
5
- var _ = {
6
+ var y = i[300], b = {
7
+ tracks: [],
8
+ gradient: !1,
9
+ loopHold: 0
10
+ }, x = {
6
11
  name: "DtMotionText",
7
12
  props: {
8
13
  text: {
@@ -17,7 +22,7 @@ var _ = {
17
22
  speed: {
18
23
  type: [String, Number],
19
24
  default: 300,
20
- validator: (e) => n.includes(String(e))
25
+ validator: (e) => r.includes(String(e))
21
26
  },
22
27
  autoStart: {
23
28
  type: Boolean,
@@ -45,30 +50,70 @@ var _ = {
45
50
  ],
46
51
  data() {
47
52
  return {
48
- words: [],
49
- visibleWordCount: 0,
50
- visibleCharsPerWord: [],
53
+ words: s(this.text),
54
+ wordWidths: [],
55
+ isRtl: !1,
51
56
  isAnimating: !1,
52
57
  isPaused: !1,
58
+ isComplete: !1,
59
+ isRestarting: !1,
53
60
  isLooped: !1,
61
+ isUnmounted: !1,
54
62
  animationTimeouts: [],
63
+ timelineStartedAt: 0,
64
+ timelineElapsed: 0,
55
65
  prefersReducedMotion: !1,
56
- animationKey: 0
66
+ animationKey: 0,
67
+ cssIterations: 1
57
68
  };
58
69
  },
59
70
  computed: {
60
- timing() {
61
- return r[String(this.speed)];
71
+ modeSettings() {
72
+ return n[this.animationMode] ?? b;
73
+ },
74
+ isWholeText() {
75
+ return !!this.modeSettings.wholeText;
76
+ },
77
+ speedScale() {
78
+ return (i[String(this.speed)] ?? y).duration / y.duration;
62
79
  },
63
80
  componentStyles() {
64
- return {
65
- "--d-motion-text-duration": `${this.timing.duration}ms`,
66
- "--d-motion-text-char-duration": `${this.timing.duration}ms`,
67
- "--d-motion-text-word-duration": `${this.timing.duration * 2}ms`
68
- };
81
+ let e = {};
82
+ return this.modeSettings.tracks.forEach((t) => {
83
+ Object.entries(a[t]).forEach(([n, r]) => {
84
+ e[`--d-motion-text-${t}-${n}`] = `${Math.round(r * this.speedScale)}ms`;
85
+ });
86
+ }), e;
87
+ },
88
+ wordStyles() {
89
+ let e = this.modeSettings.gradient ? o(this.wordWidths, this.isRtl) : [];
90
+ return this.words.map((t, n) => {
91
+ let r = e[n];
92
+ return {
93
+ "--d-motion-text-word-index": n,
94
+ ...r && {
95
+ "--d-motion-text-gradient-size": r.size,
96
+ "--d-motion-text-gradient-position": r.position
97
+ }
98
+ };
99
+ });
100
+ },
101
+ wordEndTimes() {
102
+ return this.words.map((e, t) => {
103
+ let n = this.modeSettings.tracks.map((e) => {
104
+ let { delay: n, stagger: r, duration: i } = a[e];
105
+ return n + r * t + i;
106
+ });
107
+ return Math.max(0, ...n) * this.speedScale;
108
+ });
69
109
  },
70
- isStaticAnimationMode() {
71
- return this.animationMode === "gradient-sweep" || this.animationMode === "shimmer";
110
+ cycleDuration() {
111
+ if (!this.isWholeText) return Math.max(0, ...this.wordEndTimes);
112
+ let e = this.modeSettings.tracks.map((e) => {
113
+ let { delay: t, duration: n } = a[e];
114
+ return t + n;
115
+ });
116
+ return Math.max(0, ...e) * this.speedScale * this.cssIterations;
72
117
  },
73
118
  motionTextClasses() {
74
119
  return [
@@ -77,192 +122,187 @@ var _ = {
77
122
  {
78
123
  "d-motion-text--animating": this.isAnimating,
79
124
  "d-motion-text--paused": this.isPaused,
80
- "d-motion-text--looped": this.isLooped
125
+ "d-motion-text--complete": this.isComplete,
126
+ "d-motion-text--restarting": this.isRestarting,
127
+ "d-motion-text--looped": this.isLooped,
128
+ "d-motion-text--respects-reduced-motion": this.respectsReducedMotion
81
129
  }
82
130
  ];
83
131
  }
84
132
  },
85
133
  watch: {
86
134
  text() {
87
- this.reset(), this.initializeContent();
135
+ if (this.isWholeText) {
136
+ this.words = s(this.text), this.isComplete && this.autoStart && !this.loop && (this.reset(), this.$nextTick(() => this.start()));
137
+ return;
138
+ }
139
+ if (this.reset(), this.text) {
140
+ this.initializeContent();
141
+ return;
142
+ }
143
+ this.words = [], this.$nextTick(() => this.initializeContent());
144
+ },
145
+ animationMode(e, t) {
146
+ let r = !!n[t]?.wholeText;
147
+ if (!this.text && r !== this.isWholeText) {
148
+ let e = this.isAnimating;
149
+ this.reset(), this.words = [], this.$nextTick(() => {
150
+ this.words = s(this.getSlotText()), this.wordWidths = [], e && this.$nextTick(() => this.start());
151
+ });
152
+ return;
153
+ }
154
+ this.restartIfAnimating();
155
+ },
156
+ autoStart(e) {
157
+ e && !this.isAnimating && (this.isWholeText || this.words.length) && this.$nextTick(() => this.start());
158
+ },
159
+ speed() {
160
+ this.restartIfAnimating();
88
161
  },
89
162
  loop: {
90
163
  handler(e) {
91
- this.isLooped = e;
164
+ this.isLooped = e, this.isAnimating && !this.isPaused && (this.timelineElapsed = Date.now() - this.timelineStartedAt, this.clearTimeouts(), this.runTimeline());
92
165
  },
93
166
  immediate: !0
94
167
  }
95
168
  },
96
169
  mounted() {
97
- this.checkReducedMotion(), this.initializeContent();
170
+ this.initWatchReducedMotion(), this.initializeContent(), document.fonts?.ready.then(() => {
171
+ !this.isUnmounted && this.isAnimating && this.measureWords();
172
+ });
98
173
  },
99
174
  beforeUnmount() {
100
- this.clearTimeouts();
175
+ this.isUnmounted = !0, this.clearTimeouts(), this.stopWatchingReducedMotion?.();
101
176
  },
102
177
  methods: {
103
- processTextToChars(e) {
104
- let t = [], n = (e, r = 0) => {
105
- if (e.nodeType === Node.TEXT_NODE) {
106
- let n = e.textContent?.match(/\S+\s*/g) || [];
107
- return t.push(...n.map((e, t) => ({
108
- text: e,
109
- chars: e.split(""),
110
- index: r + t
111
- }))), r + n.length;
112
- } else if (e.nodeType === Node.ELEMENT_NODE) {
113
- let t = r;
114
- return Array.from(e.childNodes).forEach((e) => {
115
- t = n(e, t);
116
- }), t;
117
- }
118
- return r;
119
- };
120
- return n(e), t;
178
+ getSlotText() {
179
+ return this.$refs.slotRef?.textContent || "";
121
180
  },
122
- processDirectText(e) {
123
- return e ? (e.match(/\S+\s*/g) || []).map((e, t) => ({
124
- text: e,
125
- chars: e.split(""),
126
- index: t
127
- })) : [];
181
+ initWatchReducedMotion() {
182
+ if (typeof window > "u" || !window.matchMedia) return;
183
+ let e = window.matchMedia("(prefers-reduced-motion: reduce)"), t = (e) => {
184
+ this.prefersReducedMotion = e.matches, e.matches && this.respectsReducedMotion && this.isAnimating && this.skipToEnd();
185
+ };
186
+ this.prefersReducedMotion = e.matches, e.addEventListener?.("change", t), this.stopWatchingReducedMotion = () => e.removeEventListener?.("change", t);
128
187
  },
129
- checkReducedMotion() {
130
- typeof window < "u" && window.matchMedia && (this.prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches);
188
+ measureWords() {
189
+ if (!this.modeSettings.gradient) return;
190
+ let e = this.$refs.contentRef?.querySelectorAll(".d-motion-text__word") || [], t = Array.from(e, (e) => e.getBoundingClientRect().width);
191
+ this.isRtl = window.getComputedStyle(this.$el).direction === "rtl", this.wordWidths = t.length === this.words.length && t.every((e) => e > 0) ? t : this.words.map((e) => e.text.length);
131
192
  },
132
193
  clearTimeouts() {
133
194
  this.animationTimeouts.forEach((e) => clearTimeout(e)), this.animationTimeouts = [];
134
195
  },
196
+ schedule(e, t) {
197
+ this.animationTimeouts.push(setTimeout(t, Math.max(0, e)));
198
+ },
199
+ runTimeline() {
200
+ let e = this.timelineElapsed, t = this.words.length, n = this.cycleDuration;
201
+ if (this.timelineStartedAt = Date.now() - e, (this.isWholeText ? [] : this.wordEndTimes).forEach((n, r) => {
202
+ n <= e || this.schedule(n - e, () => {
203
+ this.$emit("progress", {
204
+ wordsComplete: r + 1,
205
+ totalWords: t,
206
+ progress: (r + 1) / t
207
+ });
208
+ });
209
+ }), n > e && this.schedule(n - e, () => this.completeAnimation()), this.loop) {
210
+ let t = n + this.modeSettings.loopHold * this.speedScale;
211
+ this.schedule(t - e, () => this.restartCycle());
212
+ } else n <= e && this.finishAnimation();
213
+ },
135
214
  start() {
136
- if (!this.isAnimating) {
137
- if (this.isAnimating = !0, this.isPaused = !1, this.$emit("start"), this.respectsReducedMotion && this.prefersReducedMotion) {
215
+ if (!(this.isAnimating || this.isUnmounted)) {
216
+ if (this.clearTimeouts(), this.isAnimating = !0, this.isPaused = !1, this.isComplete = !1, this.$emit("start"), this.respectsReducedMotion && this.prefersReducedMotion) {
138
217
  this.showAllContent();
139
218
  return;
140
219
  }
141
- if (this.animationMode === "none") {
220
+ if (!this.modeSettings.tracks.length || !this.isWholeText && !this.words.length) {
142
221
  this.showAllContent();
143
222
  return;
144
223
  }
145
- this.isStaticAnimationMode || this.showNextWord();
224
+ this.measureWords(), this.cssIterations = this.readCssIterations(), this.timelineElapsed = 0, this.runTimeline();
146
225
  }
147
226
  },
227
+ readCssIterations() {
228
+ if (!this.isWholeText || this.loop) return 1;
229
+ let e = parseFloat(window.getComputedStyle(this.$el).animationIterationCount);
230
+ return Number.isFinite(e) && e > 1 ? e : 1;
231
+ },
148
232
  pause() {
149
- !this.isAnimating || this.isPaused || (this.isPaused = !0, this.clearTimeouts(), this.$emit("pause"));
233
+ !this.isAnimating || this.isPaused || (this.timelineElapsed = Date.now() - this.timelineStartedAt, this.clearTimeouts(), this.isPaused = !0, this.$emit("pause"));
150
234
  },
151
235
  resume() {
152
- this.isPaused && (this.isPaused = !1, this.$emit("resume"), this.showNextWord());
236
+ this.isPaused && (this.isPaused = !1, this.$emit("resume"), this.runTimeline());
153
237
  },
154
238
  reset() {
155
- this.clearTimeouts(), this.isAnimating = !1, this.isPaused = !1, this.visibleWordCount = 0, this.visibleCharsPerWord = Array(this.words.length).fill(0), this.animationKey++;
239
+ this.clearTimeouts(), this.isAnimating = !1, this.isPaused = !1, this.isComplete = !1, this.timelineElapsed = 0, this.animationKey++, this.replayAnimations();
156
240
  },
157
241
  skipToEnd() {
158
242
  this.showAllContent();
159
243
  },
160
244
  showAllContent() {
161
- this.visibleWordCount = this.words.length, this.visibleCharsPerWord = this.words.map((e) => e.chars.length), setTimeout(() => {
162
- this.isAnimating = !1, this.$emit("complete");
163
- }, 0);
245
+ this.finishAnimation(), this.isPaused = !1, this.schedule(0, () => this.$emit("complete"));
164
246
  },
165
- showNextWord() {
166
- if (this.isPaused || this.visibleWordCount >= this.words.length) {
167
- this.visibleWordCount >= this.words.length && this.completeAnimation();
168
- return;
169
- }
170
- let e = setTimeout(() => {
171
- this.visibleWordCount++, this.$emit("progress", {
172
- wordsComplete: this.visibleWordCount,
173
- totalWords: this.words.length,
174
- progress: this.visibleWordCount / this.words.length
175
- }), this.animateCharsForWord(this.visibleWordCount - 1);
176
- }, this.timing.wordDelay);
177
- this.animationTimeouts.push(e);
178
- },
179
- animateCharsForWord(e) {
180
- if (this.isPaused || e >= this.words.length) return;
181
- this.visibleCharsPerWord[e] = 0;
182
- let t = this.words[e].chars.length, n = () => {
183
- if (this.isPaused || this.visibleCharsPerWord[e] >= t) {
184
- this.visibleCharsPerWord[e] >= t && this.showNextWord();
185
- return;
186
- }
187
- this.visibleCharsPerWord[e]++;
188
- let r = setTimeout(n, this.timing.characterDelay);
189
- this.animationTimeouts.push(r);
190
- };
191
- n();
247
+ finishAnimation() {
248
+ this.clearTimeouts(), this.isAnimating = !1, this.isComplete = !0;
249
+ },
250
+ restartIfAnimating() {
251
+ this.isAnimating && (this.reset(), this.$nextTick(() => this.start()));
192
252
  },
193
253
  completeAnimation() {
194
- if (this.isAnimating = !1, this.clearTimeouts(), this.$emit("complete"), this.loop) {
195
- let e = setTimeout(() => {
196
- this.reset(), this.$nextTick(() => {
197
- this.start();
198
- });
199
- }, 500);
200
- this.animationTimeouts.push(e);
201
- }
254
+ this.$emit("complete"), this.loop || this.finishAnimation();
255
+ },
256
+ replayAnimations(e) {
257
+ this.isRestarting = !0, this.$nextTick(() => {
258
+ this.$el?.getBoundingClientRect?.(), this.isRestarting = !1, e?.();
259
+ });
260
+ },
261
+ restartCycle() {
262
+ this.isUnmounted || (this.clearTimeouts(), this.replayAnimations(() => {
263
+ this.measureWords(), this.timelineElapsed = 0, this.$emit("start"), this.runTimeline();
264
+ }));
202
265
  },
203
266
  initializeContent() {
204
- if (this.isStaticAnimationMode) {
205
- this.autoStart && this.$nextTick(() => this.start());
206
- return;
207
- }
208
- this.text ? this.words = this.processDirectText(this.text) : this.$refs.contentRef && (this.words = this.processTextToChars(this.$refs.contentRef)), this.visibleCharsPerWord = Array(this.words.length).fill(0), this.visibleWordCount = 0, this.autoStart && this.words.length > 0 && this.$nextTick(() => this.start());
267
+ this.words = s(this.text || this.getSlotText()), this.wordWidths = [], this.autoStart && (this.isWholeText || this.words.length > 0) && this.$nextTick(() => this.start());
209
268
  }
210
269
  }
211
- }, v = [
212
- "data-text-content",
213
- "aria-live",
214
- "aria-label"
215
- ], y = {
270
+ }, S = ["aria-live", "aria-label"], C = {
216
271
  key: 0,
272
+ "data-qa": "dt-motion-text-sr-only",
217
273
  class: "d-motion-text__sr-only"
218
- }, b = ["aria-hidden"], x = ["data-text-content"], S = {
274
+ }, w = ["aria-hidden"], T = ["aria-hidden"], E = {
219
275
  key: 3,
276
+ ref: "slotRef",
220
277
  class: "d-motion-text__fallback"
221
278
  };
222
- function C(e, t, n, r, _, C) {
223
- return f(), c("span", {
224
- ref: "contentRef",
225
- class: u(C.motionTextClasses),
226
- style: d(C.componentStyles),
227
- "data-text-content": C.isStaticAnimationMode ? n.text : void 0,
228
- "aria-live": _.isAnimating ? "polite" : "off",
279
+ function D(e, t, n, r, i, a) {
280
+ return h(), u("span", {
281
+ "data-qa": "dt-motion-text",
282
+ class: p(a.motionTextClasses),
283
+ style: m(a.componentStyles),
284
+ "aria-live": i.isAnimating ? "polite" : "off",
229
285
  "aria-label": n.screenReaderText || void 0
230
- }, [
231
- n.screenReaderText ? (f(), c("span", y, h(n.screenReaderText), 1)) : s("", !0),
232
- C.isStaticAnimationMode ? (f(), c(i, { key: 1 }, [l(h(n.text) + " ", 1), n.text ? s("", !0) : m(e.$slots, "default", { key: 0 })], 64)) : (f(), c("span", {
233
- key: _.animationKey,
234
- class: "d-motion-text__content",
235
- "aria-hidden": _.isAnimating
236
- }, [(f(!0), c(i, null, p(_.words, (e, t) => (f(), o(a, {
237
- key: `${_.animationKey}-${t}`,
238
- name: `d-motion-text-word-${n.animationMode}`
239
- }, {
240
- default: g(() => [t < _.visibleWordCount ? (f(), c("span", {
241
- key: 0,
242
- class: "d-motion-text__word",
243
- "data-text-content": e.text,
244
- style: d({ "--word-index": t })
245
- }, [(f(!0), c(i, null, p(e.chars, (e, r) => (f(), o(a, {
246
- key: `${_.animationKey}-${t}-${r}`,
247
- name: `d-motion-text-char-${n.animationMode}`
248
- }, {
249
- default: g(() => [r < _.visibleCharsPerWord[t] ? (f(), c("span", {
250
- key: 0,
251
- class: "d-motion-text__char",
252
- style: d({
253
- "--char-index": r,
254
- "--char-delay": `${r * C.timing.characterDelay}ms`
255
- })
256
- }, h(e), 5)) : s("", !0)]),
257
- _: 2
258
- }, 1032, ["name"]))), 128))], 12, x)) : s("", !0)]),
259
- _: 2
260
- }, 1032, ["name"]))), 128))], 8, b)),
261
- !_.words.length && !n.text && !C.isStaticAnimationMode ? (f(), c("span", S, [m(e.$slots, "default")])) : s("", !0)
262
- ], 14, v);
286
+ }, [n.screenReaderText ? (h(), u("span", C, v(n.screenReaderText), 1)) : l("", !0), a.isWholeText ? (h(), u("span", {
287
+ key: 1,
288
+ ref: "slotRef",
289
+ "data-qa": "dt-motion-text-content",
290
+ class: "d-motion-text__content",
291
+ "aria-hidden": n.screenReaderText ? "true" : void 0
292
+ }, [f(v(n.text), 1), n.text ? l("", !0) : _(e.$slots, "default", { key: 0 })], 8, w)) : i.words.length ? (h(), u("span", {
293
+ ref: "contentRef",
294
+ key: i.animationKey,
295
+ "data-qa": "dt-motion-text-content",
296
+ class: "d-motion-text__content",
297
+ "aria-hidden": n.screenReaderText ? "true" : void 0
298
+ }, [(h(!0), u(c, null, g(i.words, (e, t) => (h(), u(c, { key: `${i.animationKey}-${t}` }, [d("span", {
299
+ "data-qa": "dt-motion-text-word",
300
+ class: "d-motion-text__word",
301
+ style: m(a.wordStyles[t])
302
+ }, v(e.text), 5), f(v(e.space), 1)], 64))), 128))], 8, T)) : (h(), u("span", E, [_(e.$slots, "default")], 512))], 14, S);
263
303
  }
264
- var w = /* @__PURE__ */ e(_, [["render", C]]);
304
+ var O = /* @__PURE__ */ e(x, [["render", D]]);
265
305
  //#endregion
266
- export { w as default };
306
+ export { O as default };
267
307
 
268
308
  //# sourceMappingURL=motion-text.js.map