le-kit 0.5.1 → 0.5.3

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 (317) hide show
  1. package/LLM_CONTEXT.md +22 -0
  2. package/dist/cjs/le-bar_16.cjs.entry.js +945 -1257
  3. package/dist/cjs/le-box.cjs.entry.js +40 -88
  4. package/dist/cjs/le-breadcrumbs.cjs.entry.js +223 -0
  5. package/dist/cjs/le-card.cjs.entry.js +11 -11
  6. package/dist/cjs/le-code-input.cjs.entry.js +76 -110
  7. package/dist/cjs/le-combobox.cjs.entry.js +126 -153
  8. package/dist/cjs/le-header-placeholder.cjs.entry.js +1 -1
  9. package/dist/cjs/le-kit.cjs.js +1 -1
  10. package/dist/cjs/le-multiselect.cjs.entry.js +149 -171
  11. package/dist/cjs/le-number-input.cjs.entry.js +89 -129
  12. package/dist/cjs/le-round-progress.cjs.entry.js +6 -11
  13. package/dist/cjs/le-segmented-control.cjs.entry.js +77 -87
  14. package/dist/cjs/le-side-panel-toggle.cjs.entry.js +59 -75
  15. package/dist/cjs/le-side-panel.cjs.entry.js +130 -137
  16. package/dist/cjs/le-stack.cjs.entry.js +38 -51
  17. package/dist/cjs/le-tab-bar.cjs.entry.js +80 -89
  18. package/dist/cjs/le-tab-panel.cjs.entry.js +21 -39
  19. package/dist/cjs/le-tab.cjs.entry.js +53 -91
  20. package/dist/cjs/le-tabs.cjs.entry.js +112 -122
  21. package/dist/cjs/le-tag.cjs.entry.js +23 -40
  22. package/dist/cjs/le-text.cjs.entry.js +131 -148
  23. package/dist/cjs/le-turntable.cjs.entry.js +17 -25
  24. package/dist/cjs/loader.cjs.js +1 -1
  25. package/dist/collection/collection-manifest.json +1 -0
  26. package/dist/collection/components/le-bar/le-bar.js +132 -139
  27. package/dist/collection/components/le-bar/le-bar.js.map +1 -1
  28. package/dist/collection/components/le-box/le-box.js +41 -88
  29. package/dist/collection/components/le-box/le-box.js.map +1 -1
  30. package/dist/collection/components/le-breadcrumbs/le-breadcrumbs.css +72 -0
  31. package/dist/collection/components/le-breadcrumbs/le-breadcrumbs.js +372 -0
  32. package/dist/collection/components/le-breadcrumbs/le-breadcrumbs.js.map +1 -0
  33. package/dist/collection/components/le-button/le-button.js +50 -79
  34. package/dist/collection/components/le-button/le-button.js.map +1 -1
  35. package/dist/collection/components/le-card/le-card.js +12 -11
  36. package/dist/collection/components/le-card/le-card.js.map +1 -1
  37. package/dist/collection/components/le-checkbox/le-checkbox.js +27 -42
  38. package/dist/collection/components/le-checkbox/le-checkbox.js.map +1 -1
  39. package/dist/collection/components/le-code-input/le-code-input.js +77 -110
  40. package/dist/collection/components/le-code-input/le-code-input.js.map +1 -1
  41. package/dist/collection/components/le-collapse/le-collapse.js +15 -14
  42. package/dist/collection/components/le-collapse/le-collapse.js.map +1 -1
  43. package/dist/collection/components/le-combobox/le-combobox.js +127 -153
  44. package/dist/collection/components/le-combobox/le-combobox.js.map +1 -1
  45. package/dist/collection/components/le-component/le-component.js +14 -38
  46. package/dist/collection/components/le-component/le-component.js.map +1 -1
  47. package/dist/collection/components/le-current-heading/le-current-heading.js +6 -5
  48. package/dist/collection/components/le-current-heading/le-current-heading.js.map +1 -1
  49. package/dist/collection/components/le-dropdown-base/le-dropdown-base.js +139 -165
  50. package/dist/collection/components/le-dropdown-base/le-dropdown-base.js.map +1 -1
  51. package/dist/collection/components/le-header/le-header.js +22 -45
  52. package/dist/collection/components/le-header/le-header.js.map +1 -1
  53. package/dist/collection/components/le-header-placeholder/le-header-placeholder.js +1 -1
  54. package/dist/collection/components/le-icon/le-icon.js +14 -14
  55. package/dist/collection/components/le-icon/le-icon.js.map +1 -1
  56. package/dist/collection/components/le-multiselect/le-multiselect.js +150 -171
  57. package/dist/collection/components/le-multiselect/le-multiselect.js.map +1 -1
  58. package/dist/collection/components/le-navigation/le-navigation.js +118 -128
  59. package/dist/collection/components/le-navigation/le-navigation.js.map +1 -1
  60. package/dist/collection/components/le-number-input/le-number-input.js +90 -129
  61. package/dist/collection/components/le-number-input/le-number-input.js.map +1 -1
  62. package/dist/collection/components/le-popover/le-popover.css +2 -1
  63. package/dist/collection/components/le-popover/le-popover.js +101 -126
  64. package/dist/collection/components/le-popover/le-popover.js.map +1 -1
  65. package/dist/collection/components/le-popup/le-popup.js +89 -115
  66. package/dist/collection/components/le-popup/le-popup.js.map +1 -1
  67. package/dist/collection/components/le-round-progress/le-round-progress.js +7 -12
  68. package/dist/collection/components/le-round-progress/le-round-progress.js.map +1 -1
  69. package/dist/collection/components/le-scroll-progress/le-scroll-progress.js +6 -7
  70. package/dist/collection/components/le-scroll-progress/le-scroll-progress.js.map +1 -1
  71. package/dist/collection/components/le-segmented-control/le-segmented-control.js +78 -87
  72. package/dist/collection/components/le-segmented-control/le-segmented-control.js.map +1 -1
  73. package/dist/collection/components/le-select/le-select.js +88 -110
  74. package/dist/collection/components/le-select/le-select.js.map +1 -1
  75. package/dist/collection/components/le-side-panel/le-side-panel.css +10 -1
  76. package/dist/collection/components/le-side-panel/le-side-panel.js +131 -136
  77. package/dist/collection/components/le-side-panel/le-side-panel.js.map +1 -1
  78. package/dist/collection/components/le-side-panel-toggle/le-side-panel-toggle.js +60 -75
  79. package/dist/collection/components/le-side-panel-toggle/le-side-panel-toggle.js.map +1 -1
  80. package/dist/collection/components/le-slot/le-slot.js +96 -144
  81. package/dist/collection/components/le-slot/le-slot.js.map +1 -1
  82. package/dist/collection/components/le-stack/le-stack.js +39 -51
  83. package/dist/collection/components/le-stack/le-stack.js.map +1 -1
  84. package/dist/collection/components/le-string-input/le-string-input.js +41 -84
  85. package/dist/collection/components/le-string-input/le-string-input.js.map +1 -1
  86. package/dist/collection/components/le-tab/le-tab.js +54 -91
  87. package/dist/collection/components/le-tab/le-tab.js.map +1 -1
  88. package/dist/collection/components/le-tab-bar/le-tab-bar.js +81 -89
  89. package/dist/collection/components/le-tab-bar/le-tab-bar.js.map +1 -1
  90. package/dist/collection/components/le-tab-panel/le-tab-panel.js +22 -39
  91. package/dist/collection/components/le-tab-panel/le-tab-panel.js.map +1 -1
  92. package/dist/collection/components/le-tabs/le-tabs.js +113 -122
  93. package/dist/collection/components/le-tabs/le-tabs.js.map +1 -1
  94. package/dist/collection/components/le-tag/le-tag.js +25 -40
  95. package/dist/collection/components/le-tag/le-tag.js.map +1 -1
  96. package/dist/collection/components/le-text/le-text.js +132 -148
  97. package/dist/collection/components/le-text/le-text.js.map +1 -1
  98. package/dist/collection/components/le-turntable/le-turntable.js +18 -26
  99. package/dist/collection/components/le-turntable/le-turntable.js.map +1 -1
  100. package/dist/collection/dist/components/assets/custom-elements.json +1371 -1043
  101. package/dist/collection/dist/components/assets/icons/arrow-left.json +21 -0
  102. package/dist/collection/dist/components/assets/icons/arrow-right.json +21 -0
  103. package/dist/collection/dist/components/assets/icons/check.json +12 -0
  104. package/dist/collection/dist/components/assets/icons/chevron-down.json +1 -2
  105. package/dist/collection/dist/components/assets/icons/chevron-left.json +12 -0
  106. package/dist/collection/dist/components/assets/icons/chevron-right.json +12 -0
  107. package/dist/collection/dist/components/assets/icons/chevron-up.json +12 -0
  108. package/dist/components/assets/custom-elements.json +1371 -1043
  109. package/dist/components/assets/icons/arrow-left.json +21 -0
  110. package/dist/components/assets/icons/arrow-right.json +21 -0
  111. package/dist/components/assets/icons/check.json +12 -0
  112. package/dist/components/assets/icons/chevron-down.json +1 -2
  113. package/dist/components/assets/icons/chevron-left.json +12 -0
  114. package/dist/components/assets/icons/chevron-right.json +12 -0
  115. package/dist/components/assets/icons/chevron-up.json +12 -0
  116. package/dist/components/le-bar2.js +132 -140
  117. package/dist/components/le-bar2.js.map +1 -1
  118. package/dist/components/le-box.js +41 -89
  119. package/dist/components/le-box.js.map +1 -1
  120. package/dist/components/le-breadcrumbs.d.ts +11 -0
  121. package/dist/components/le-breadcrumbs.js +327 -0
  122. package/dist/components/le-breadcrumbs.js.map +1 -0
  123. package/dist/components/le-button2.js +405 -619
  124. package/dist/components/le-button2.js.map +1 -1
  125. package/dist/components/le-card.js +12 -12
  126. package/dist/components/le-card.js.map +1 -1
  127. package/dist/components/le-code-input.js +77 -111
  128. package/dist/components/le-code-input.js.map +1 -1
  129. package/dist/components/le-collapse2.js +15 -15
  130. package/dist/components/le-collapse2.js.map +1 -1
  131. package/dist/components/le-combobox.js +127 -154
  132. package/dist/components/le-combobox.js.map +1 -1
  133. package/dist/components/le-current-heading.js +6 -6
  134. package/dist/components/le-current-heading.js.map +1 -1
  135. package/dist/components/le-dropdown-base2.js +139 -166
  136. package/dist/components/le-dropdown-base2.js.map +1 -1
  137. package/dist/components/le-header-placeholder.js +1 -1
  138. package/dist/components/le-header.js +22 -46
  139. package/dist/components/le-header.js.map +1 -1
  140. package/dist/components/le-icon2.js +14 -15
  141. package/dist/components/le-icon2.js.map +1 -1
  142. package/dist/components/le-multiselect.js +150 -172
  143. package/dist/components/le-multiselect.js.map +1 -1
  144. package/dist/components/le-navigation.js +1 -494
  145. package/dist/components/le-navigation.js.map +1 -1
  146. package/dist/components/le-navigation2.js +488 -0
  147. package/dist/components/le-navigation2.js.map +1 -0
  148. package/dist/components/le-number-input.js +90 -130
  149. package/dist/components/le-number-input.js.map +1 -1
  150. package/dist/components/le-popover2.js +103 -128
  151. package/dist/components/le-popover2.js.map +1 -1
  152. package/dist/components/le-round-progress.js +7 -12
  153. package/dist/components/le-round-progress.js.map +1 -1
  154. package/dist/components/le-scroll-progress.js +6 -8
  155. package/dist/components/le-scroll-progress.js.map +1 -1
  156. package/dist/components/le-segmented-control.js +78 -88
  157. package/dist/components/le-segmented-control.js.map +1 -1
  158. package/dist/components/le-side-panel-toggle2.js +60 -76
  159. package/dist/components/le-side-panel-toggle2.js.map +1 -1
  160. package/dist/components/le-side-panel.js +133 -139
  161. package/dist/components/le-side-panel.js.map +1 -1
  162. package/dist/components/le-stack.js +39 -52
  163. package/dist/components/le-stack.js.map +1 -1
  164. package/dist/components/le-tab-bar.js +81 -90
  165. package/dist/components/le-tab-bar.js.map +1 -1
  166. package/dist/components/le-tab-panel.js +22 -40
  167. package/dist/components/le-tab-panel.js.map +1 -1
  168. package/dist/components/le-tab2.js +54 -92
  169. package/dist/components/le-tab2.js.map +1 -1
  170. package/dist/components/le-tabs.js +113 -123
  171. package/dist/components/le-tabs.js.map +1 -1
  172. package/dist/components/le-tag2.js +24 -41
  173. package/dist/components/le-tag2.js.map +1 -1
  174. package/dist/components/le-text.js +132 -149
  175. package/dist/components/le-text.js.map +1 -1
  176. package/dist/components/le-turntable.js +18 -26
  177. package/dist/components/le-turntable.js.map +1 -1
  178. package/dist/docs.json +294 -2
  179. package/dist/esm/le-bar_16.entry.js +946 -1258
  180. package/dist/esm/le-box.entry.js +41 -89
  181. package/dist/esm/le-box.entry.js.map +1 -1
  182. package/dist/esm/le-breadcrumbs.entry.js +221 -0
  183. package/dist/esm/le-breadcrumbs.entry.js.map +1 -0
  184. package/dist/esm/le-card.entry.js +12 -12
  185. package/dist/esm/le-card.entry.js.map +1 -1
  186. package/dist/esm/le-code-input.entry.js +77 -111
  187. package/dist/esm/le-code-input.entry.js.map +1 -1
  188. package/dist/esm/le-combobox.entry.js +127 -154
  189. package/dist/esm/le-combobox.entry.js.map +1 -1
  190. package/dist/esm/le-header-placeholder.entry.js +1 -1
  191. package/dist/esm/le-kit.js +1 -1
  192. package/dist/esm/le-multiselect.entry.js +150 -172
  193. package/dist/esm/le-multiselect.entry.js.map +1 -1
  194. package/dist/esm/le-number-input.entry.js +90 -130
  195. package/dist/esm/le-number-input.entry.js.map +1 -1
  196. package/dist/esm/le-round-progress.entry.js +7 -12
  197. package/dist/esm/le-round-progress.entry.js.map +1 -1
  198. package/dist/esm/le-segmented-control.entry.js +78 -88
  199. package/dist/esm/le-segmented-control.entry.js.map +1 -1
  200. package/dist/esm/le-side-panel-toggle.entry.js +60 -76
  201. package/dist/esm/le-side-panel-toggle.entry.js.map +1 -1
  202. package/dist/esm/le-side-panel.entry.js +131 -138
  203. package/dist/esm/le-side-panel.entry.js.map +1 -1
  204. package/dist/esm/le-stack.entry.js +39 -52
  205. package/dist/esm/le-stack.entry.js.map +1 -1
  206. package/dist/esm/le-tab-bar.entry.js +81 -90
  207. package/dist/esm/le-tab-bar.entry.js.map +1 -1
  208. package/dist/esm/le-tab-panel.entry.js +22 -40
  209. package/dist/esm/le-tab-panel.entry.js.map +1 -1
  210. package/dist/esm/le-tab.entry.js +54 -92
  211. package/dist/esm/le-tab.entry.js.map +1 -1
  212. package/dist/esm/le-tabs.entry.js +113 -123
  213. package/dist/esm/le-tabs.entry.js.map +1 -1
  214. package/dist/esm/le-tag.entry.js +23 -40
  215. package/dist/esm/le-tag.entry.js.map +1 -1
  216. package/dist/esm/le-text.entry.js +132 -149
  217. package/dist/esm/le-text.entry.js.map +1 -1
  218. package/dist/esm/le-turntable.entry.js +18 -26
  219. package/dist/esm/le-turntable.entry.js.map +1 -1
  220. package/dist/esm/loader.js +1 -1
  221. package/dist/le-kit/dist/components/assets/custom-elements.json +1371 -1043
  222. package/dist/le-kit/dist/components/assets/icons/arrow-left.json +21 -0
  223. package/dist/le-kit/dist/components/assets/icons/arrow-right.json +21 -0
  224. package/dist/le-kit/dist/components/assets/icons/check.json +12 -0
  225. package/dist/le-kit/dist/components/assets/icons/chevron-down.json +1 -2
  226. package/dist/le-kit/dist/components/assets/icons/chevron-left.json +12 -0
  227. package/dist/le-kit/dist/components/assets/icons/chevron-right.json +12 -0
  228. package/dist/le-kit/dist/components/assets/icons/chevron-up.json +12 -0
  229. package/dist/le-kit/le-kit.esm.js +1 -1
  230. package/dist/le-kit/p-3067b18f.entry.js +2 -0
  231. package/dist/le-kit/p-3067b18f.entry.js.map +1 -0
  232. package/dist/le-kit/p-34c4d97d.entry.js +2 -0
  233. package/dist/le-kit/p-34c4d97d.entry.js.map +1 -0
  234. package/dist/le-kit/p-45182541.entry.js +2 -0
  235. package/dist/le-kit/p-45182541.entry.js.map +1 -0
  236. package/dist/le-kit/p-52a41c96.entry.js +2 -0
  237. package/dist/le-kit/p-52a41c96.entry.js.map +1 -0
  238. package/dist/le-kit/p-55fb5dd2.entry.js +2 -0
  239. package/dist/le-kit/p-55fb5dd2.entry.js.map +1 -0
  240. package/dist/le-kit/{p-ab6c1def.entry.js → p-649025f4.entry.js} +2 -2
  241. package/dist/le-kit/p-649025f4.entry.js.map +1 -0
  242. package/dist/le-kit/p-67930309.entry.js +2 -0
  243. package/dist/le-kit/p-67930309.entry.js.map +1 -0
  244. package/dist/le-kit/p-6d222705.entry.js +2 -0
  245. package/dist/le-kit/p-6d222705.entry.js.map +1 -0
  246. package/dist/le-kit/p-8049e0c2.entry.js +2 -0
  247. package/dist/le-kit/p-8049e0c2.entry.js.map +1 -0
  248. package/dist/le-kit/p-884f57bd.entry.js +2 -0
  249. package/dist/le-kit/p-88c70f9d.entry.js +2 -0
  250. package/dist/le-kit/p-88c70f9d.entry.js.map +1 -0
  251. package/dist/le-kit/p-96610729.entry.js +2 -0
  252. package/dist/le-kit/p-96610729.entry.js.map +1 -0
  253. package/dist/le-kit/p-a34054e0.entry.js +2 -0
  254. package/dist/le-kit/p-a34054e0.entry.js.map +1 -0
  255. package/dist/le-kit/p-a388e46a.entry.js +2 -0
  256. package/dist/le-kit/p-a388e46a.entry.js.map +1 -0
  257. package/dist/le-kit/p-c0c53650.entry.js +2 -0
  258. package/dist/le-kit/p-c0c53650.entry.js.map +1 -0
  259. package/dist/le-kit/p-cbf17514.entry.js +2 -0
  260. package/dist/le-kit/p-cbf17514.entry.js.map +1 -0
  261. package/dist/le-kit/p-d934de74.entry.js +2 -0
  262. package/dist/le-kit/p-d934de74.entry.js.map +1 -0
  263. package/dist/le-kit/p-de72c8b5.entry.js +2 -0
  264. package/dist/le-kit/p-de72c8b5.entry.js.map +1 -0
  265. package/dist/le-kit/p-e3dd0f2a.entry.js +2 -0
  266. package/dist/le-kit/p-e3dd0f2a.entry.js.map +1 -0
  267. package/dist/le-kit/p-ee170967.entry.js +2 -0
  268. package/dist/le-kit/p-ee170967.entry.js.map +1 -0
  269. package/dist/le-kit/p-eedb2f75.entry.js +2 -0
  270. package/dist/le-kit/p-eedb2f75.entry.js.map +1 -0
  271. package/dist/types/components/le-breadcrumbs/le-breadcrumbs.d.ts +57 -0
  272. package/dist/types/components/le-side-panel/le-side-panel.d.ts +2 -0
  273. package/dist/types/components.d.ts +84 -0
  274. package/package.json +1 -1
  275. package/dist/collection/assets/icons/chevron-down.svg +0 -3
  276. package/dist/collection/dist/components/assets/icons/chevron-down.svg +0 -3
  277. package/dist/components/assets/icons/chevron-down.svg +0 -3
  278. package/dist/le-kit/dist/components/assets/icons/chevron-down.svg +0 -3
  279. package/dist/le-kit/p-221d379a.entry.js +0 -2
  280. package/dist/le-kit/p-221d379a.entry.js.map +0 -1
  281. package/dist/le-kit/p-24112ca3.entry.js +0 -2
  282. package/dist/le-kit/p-24112ca3.entry.js.map +0 -1
  283. package/dist/le-kit/p-2c6d080d.entry.js +0 -2
  284. package/dist/le-kit/p-2c6d080d.entry.js.map +0 -1
  285. package/dist/le-kit/p-46276e77.entry.js +0 -2
  286. package/dist/le-kit/p-46276e77.entry.js.map +0 -1
  287. package/dist/le-kit/p-516c8531.entry.js +0 -2
  288. package/dist/le-kit/p-6b69f9a2.entry.js +0 -2
  289. package/dist/le-kit/p-6b69f9a2.entry.js.map +0 -1
  290. package/dist/le-kit/p-6d14306f.entry.js +0 -2
  291. package/dist/le-kit/p-6d14306f.entry.js.map +0 -1
  292. package/dist/le-kit/p-7bcdf2d4.entry.js +0 -2
  293. package/dist/le-kit/p-7bcdf2d4.entry.js.map +0 -1
  294. package/dist/le-kit/p-7cf1e23c.entry.js +0 -2
  295. package/dist/le-kit/p-7cf1e23c.entry.js.map +0 -1
  296. package/dist/le-kit/p-85f2fd4d.entry.js +0 -2
  297. package/dist/le-kit/p-85f2fd4d.entry.js.map +0 -1
  298. package/dist/le-kit/p-98242429.entry.js +0 -2
  299. package/dist/le-kit/p-98242429.entry.js.map +0 -1
  300. package/dist/le-kit/p-ab6c1def.entry.js.map +0 -1
  301. package/dist/le-kit/p-ae4ead64.entry.js +0 -2
  302. package/dist/le-kit/p-ae4ead64.entry.js.map +0 -1
  303. package/dist/le-kit/p-b05d4511.entry.js +0 -2
  304. package/dist/le-kit/p-b05d4511.entry.js.map +0 -1
  305. package/dist/le-kit/p-b6ac02ff.entry.js +0 -2
  306. package/dist/le-kit/p-b6ac02ff.entry.js.map +0 -1
  307. package/dist/le-kit/p-c24769e2.entry.js +0 -2
  308. package/dist/le-kit/p-c24769e2.entry.js.map +0 -1
  309. package/dist/le-kit/p-dc0445ad.entry.js +0 -2
  310. package/dist/le-kit/p-dc0445ad.entry.js.map +0 -1
  311. package/dist/le-kit/p-eb5286f2.entry.js +0 -2
  312. package/dist/le-kit/p-eb5286f2.entry.js.map +0 -1
  313. package/dist/le-kit/p-eb710c8e.entry.js +0 -2
  314. package/dist/le-kit/p-eb710c8e.entry.js.map +0 -1
  315. package/dist/le-kit/p-f78b1ee6.entry.js +0 -2
  316. package/dist/le-kit/p-f78b1ee6.entry.js.map +0 -1
  317. /package/dist/le-kit/{p-516c8531.entry.js.map → p-884f57bd.entry.js.map} +0 -0
@@ -20,61 +20,138 @@ import { observeModeChanges } from "../../utils/utils";
20
20
  * @cmsCategory Content
21
21
  */
22
22
  export class LeText {
23
- el;
24
- /**
25
- * The semantic variant/type of text element
26
- * @allowedValues p | h1 | h2 | h3 | h4 | h5 | h6 | code | quote | label | small
27
- */
28
- variant = 'p';
29
- /**
30
- * Text alignment
31
- * @allowedValues left | center | right | justify
32
- */
33
- align = 'left';
34
- /**
35
- * Text color (CSS value or theme token)
36
- */
37
- color;
38
- /**
39
- * Whether the text should truncate with ellipsis
40
- */
41
- truncate = false;
42
- /**
43
- * Maximum number of lines before truncating (requires truncate=true)
44
- */
45
- maxLines;
46
- /**
47
- * Internal state to track admin mode
48
- */
49
- adminMode = false;
50
- /**
51
- * The HTML content being edited
52
- */
53
- content = '';
54
- /**
55
- * Whether the editor is focused (shows toolbar)
56
- */
57
- isFocused = false;
58
- /**
59
- * Current selection state for toolbar button highlighting
60
- */
61
- selectionState = {
62
- isBold: false,
63
- isItalic: false,
64
- isUnderline: false,
65
- isStrikethrough: false,
66
- isLink: false,
67
- blockType: 'p',
68
- };
69
- /**
70
- * Reference to the contenteditable element
71
- */
72
- editorRef;
73
- /**
74
- * Reference to the slot element
75
- */
76
- slotRef;
77
- disconnectModeObserver;
23
+ constructor() {
24
+ /**
25
+ * The semantic variant/type of text element
26
+ * @allowedValues p | h1 | h2 | h3 | h4 | h5 | h6 | code | quote | label | small
27
+ */
28
+ this.variant = 'p';
29
+ /**
30
+ * Text alignment
31
+ * @allowedValues left | center | right | justify
32
+ */
33
+ this.align = 'left';
34
+ /**
35
+ * Whether the text should truncate with ellipsis
36
+ */
37
+ this.truncate = false;
38
+ /**
39
+ * Internal state to track admin mode
40
+ */
41
+ this.adminMode = false;
42
+ /**
43
+ * The HTML content being edited
44
+ */
45
+ this.content = '';
46
+ /**
47
+ * Whether the editor is focused (shows toolbar)
48
+ */
49
+ this.isFocused = false;
50
+ /**
51
+ * Current selection state for toolbar button highlighting
52
+ */
53
+ this.selectionState = {
54
+ isBold: false,
55
+ isItalic: false,
56
+ isUnderline: false,
57
+ isStrikethrough: false,
58
+ isLink: false,
59
+ blockType: 'p',
60
+ };
61
+ /**
62
+ * Handle input in the contenteditable
63
+ */
64
+ this.handleInput = () => {
65
+ if (this.editorRef) {
66
+ this.content = this.editorRef.innerHTML;
67
+ this.updateSelectionState();
68
+ }
69
+ };
70
+ /**
71
+ * Handle focus on the editor
72
+ */
73
+ this.handleFocus = () => {
74
+ this.isFocused = true;
75
+ this.updateSelectionState();
76
+ };
77
+ /**
78
+ * Handle blur on the editor
79
+ */
80
+ this.handleBlur = (e) => {
81
+ // Check if focus moved to toolbar
82
+ const relatedTarget = e.relatedTarget;
83
+ const toolbar = this.el.shadowRoot?.querySelector('.le-text-toolbar');
84
+ if (toolbar?.contains(relatedTarget)) {
85
+ // Focus moved to toolbar, keep it open
86
+ return;
87
+ }
88
+ // Small delay to allow toolbar clicks to register
89
+ setTimeout(() => {
90
+ if (!this.el.shadowRoot?.activeElement) {
91
+ this.isFocused = false;
92
+ this.syncContentToSlot();
93
+ }
94
+ }, 150);
95
+ };
96
+ /**
97
+ * Handle selection change to update toolbar state
98
+ */
99
+ this.handleSelectionChange = () => {
100
+ this.updateSelectionState();
101
+ };
102
+ /**
103
+ * Toggle bold formatting
104
+ */
105
+ this.toggleBold = (e) => {
106
+ e.preventDefault();
107
+ this.execCommand('bold');
108
+ };
109
+ /**
110
+ * Toggle italic formatting
111
+ */
112
+ this.toggleItalic = (e) => {
113
+ e.preventDefault();
114
+ this.execCommand('italic');
115
+ };
116
+ /**
117
+ * Toggle underline formatting
118
+ */
119
+ this.toggleUnderline = (e) => {
120
+ e.preventDefault();
121
+ this.execCommand('underline');
122
+ };
123
+ /**
124
+ * Toggle strikethrough formatting
125
+ */
126
+ this.toggleStrikethrough = (e) => {
127
+ e.preventDefault();
128
+ this.execCommand('strikeThrough');
129
+ };
130
+ /**
131
+ * Add or edit a link
132
+ */
133
+ this.toggleLink = (e) => {
134
+ e.preventDefault();
135
+ if (this.selectionState.isLink) {
136
+ // Remove link
137
+ this.execCommand('unlink');
138
+ }
139
+ else {
140
+ // Add link
141
+ const url = prompt('Enter URL:', 'https://');
142
+ if (url) {
143
+ this.execCommand('createLink', url);
144
+ }
145
+ }
146
+ };
147
+ /**
148
+ * Change the block type/variant
149
+ */
150
+ this.changeVariant = (e) => {
151
+ const select = e.target;
152
+ this.variant = select.value;
153
+ };
154
+ }
78
155
  connectedCallback() {
79
156
  this.disconnectModeObserver = observeModeChanges(this.el, mode => {
80
157
  const wasAdmin = this.adminMode;
@@ -156,47 +233,6 @@ export class LeText {
156
233
  }
157
234
  }
158
235
  }
159
- /**
160
- * Handle input in the contenteditable
161
- */
162
- handleInput = () => {
163
- if (this.editorRef) {
164
- this.content = this.editorRef.innerHTML;
165
- this.updateSelectionState();
166
- }
167
- };
168
- /**
169
- * Handle focus on the editor
170
- */
171
- handleFocus = () => {
172
- this.isFocused = true;
173
- this.updateSelectionState();
174
- };
175
- /**
176
- * Handle blur on the editor
177
- */
178
- handleBlur = (e) => {
179
- // Check if focus moved to toolbar
180
- const relatedTarget = e.relatedTarget;
181
- const toolbar = this.el.shadowRoot?.querySelector('.le-text-toolbar');
182
- if (toolbar?.contains(relatedTarget)) {
183
- // Focus moved to toolbar, keep it open
184
- return;
185
- }
186
- // Small delay to allow toolbar clicks to register
187
- setTimeout(() => {
188
- if (!this.el.shadowRoot?.activeElement) {
189
- this.isFocused = false;
190
- this.syncContentToSlot();
191
- }
192
- }, 150);
193
- };
194
- /**
195
- * Handle selection change to update toolbar state
196
- */
197
- handleSelectionChange = () => {
198
- this.updateSelectionState();
199
- };
200
236
  /**
201
237
  * Update the selection state for toolbar highlighting
202
238
  */
@@ -239,58 +275,6 @@ export class LeText {
239
275
  this.handleInput();
240
276
  this.updateSelectionState();
241
277
  }
242
- /**
243
- * Toggle bold formatting
244
- */
245
- toggleBold = (e) => {
246
- e.preventDefault();
247
- this.execCommand('bold');
248
- };
249
- /**
250
- * Toggle italic formatting
251
- */
252
- toggleItalic = (e) => {
253
- e.preventDefault();
254
- this.execCommand('italic');
255
- };
256
- /**
257
- * Toggle underline formatting
258
- */
259
- toggleUnderline = (e) => {
260
- e.preventDefault();
261
- this.execCommand('underline');
262
- };
263
- /**
264
- * Toggle strikethrough formatting
265
- */
266
- toggleStrikethrough = (e) => {
267
- e.preventDefault();
268
- this.execCommand('strikeThrough');
269
- };
270
- /**
271
- * Add or edit a link
272
- */
273
- toggleLink = (e) => {
274
- e.preventDefault();
275
- if (this.selectionState.isLink) {
276
- // Remove link
277
- this.execCommand('unlink');
278
- }
279
- else {
280
- // Add link
281
- const url = prompt('Enter URL:', 'https://');
282
- if (url) {
283
- this.execCommand('createLink', url);
284
- }
285
- }
286
- };
287
- /**
288
- * Change the block type/variant
289
- */
290
- changeVariant = (e) => {
291
- const select = e.target;
292
- this.variant = select.value;
293
- };
294
278
  /**
295
279
  * Render the formatting toolbar
296
280
  */
@@ -1 +1 @@
1
- {"version":3,"file":"le-text.js","sourceRoot":"","sources":["../../../src/components/le-text/le-text.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Host, Element, Watch } from '@stencil/core';\nimport { observeModeChanges } from '../../utils/utils';\n\n/**\n * A text component with rich text editing capabilities in admin mode.\n *\n * `le-text` renders semantic text elements (headings, paragraphs, code, quotes)\n * and provides a Notion-like rich text editor in admin mode with formatting\n * toolbar for bold, italic, links, and paragraph type selection.\n *\n * @slot - Default slot for text content\n *\n * @cssprop --le-text-color - Text color\n * @cssprop --le-text-font-size - Font size\n * @cssprop --le-text-line-height - Line height\n * @cssprop --le-text-font-weight - Font weight\n *\n * @csspart text - The text container element\n *\n * @cmsEditable true\n * @cmsCategory Content\n */\n@Component({\n tag: 'le-text',\n styleUrl: 'le-text.css',\n shadow: true,\n})\nexport class LeText {\n @Element() el: HTMLElement;\n\n /**\n * The semantic variant/type of text element\n * @allowedValues p | h1 | h2 | h3 | h4 | h5 | h6 | code | quote | label | small\n */\n @Prop({ mutable: true, reflect: true }) variant:\n | 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small' = 'p';\n\n /**\n * Text alignment\n * @allowedValues left | center | right | justify\n */\n @Prop({ reflect: true }) align: 'left' | 'center' | 'right' | 'justify' = 'left';\n\n /**\n * Text color (CSS value or theme token)\n */\n @Prop() color?: string;\n\n /**\n * Whether the text should truncate with ellipsis\n */\n @Prop() truncate: boolean = false;\n\n /**\n * Maximum number of lines before truncating (requires truncate=true)\n */\n @Prop() maxLines?: number;\n\n /**\n * Internal state to track admin mode\n */\n @State() private adminMode: boolean = false;\n\n /**\n * The HTML content being edited\n */\n @State() private content: string = '';\n\n /**\n * Whether the editor is focused (shows toolbar)\n */\n @State() private isFocused: boolean = false;\n\n /**\n * Current selection state for toolbar button highlighting\n */\n @State() private selectionState: SelectionState = {\n isBold: false,\n isItalic: false,\n isUnderline: false,\n isStrikethrough: false,\n isLink: false,\n blockType: 'p',\n };\n\n /**\n * Reference to the contenteditable element\n */\n private editorRef?: HTMLDivElement;\n\n /**\n * Reference to the slot element\n */\n private slotRef?: HTMLSlotElement;\n\n private disconnectModeObserver?: () => void;\n\n connectedCallback() {\n this.disconnectModeObserver = observeModeChanges(this.el, mode => {\n const wasAdmin = this.adminMode;\n this.adminMode = mode === 'admin';\n\n if (this.adminMode && !wasAdmin) {\n // Entering admin mode - read content from slot\n requestAnimationFrame(() => this.readSlottedContent());\n } else if (!this.adminMode && wasAdmin) {\n // Leaving admin mode - sync content back to slot\n this.syncContentToSlot();\n }\n });\n }\n\n disconnectedCallback() {\n this.disconnectModeObserver?.();\n }\n\n @Watch('variant')\n onVariantChange() {\n // When variant changes in admin mode, update the content wrapper\n if (this.adminMode && this.editorRef) {\n this.syncContentToSlot();\n }\n }\n\n /**\n * Read content from slotted elements\n */\n private readSlottedContent() {\n if (!this.slotRef) return;\n\n const assignedNodes = this.slotRef.assignedNodes({ flatten: true });\n\n // Collect all content from assigned nodes\n let html = '';\n assignedNodes.forEach(node => {\n if (node.nodeType === Node.TEXT_NODE) {\n html += node.textContent;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n html += (node as Element).innerHTML || node.textContent;\n }\n });\n\n this.content = html.trim();\n }\n\n /**\n * Sync edited content back to the slot\n */\n private syncContentToSlot() {\n if (!this.editorRef) return;\n\n const newContent = this.editorRef.innerHTML;\n\n // Update the light DOM content\n // We need to update the actual slotted content\n const slot = this.slotRef;\n if (slot) {\n const assignedNodes = slot.assignedNodes({ flatten: true });\n if (assignedNodes.length > 0) {\n const firstNode = assignedNodes[0];\n if (firstNode.nodeType === Node.ELEMENT_NODE) {\n (firstNode as Element).innerHTML = newContent;\n } else if (firstNode.nodeType === Node.TEXT_NODE) {\n // Replace text node with the new content\n const parent = firstNode.parentNode;\n if (parent) {\n // Create a temporary element to parse HTML\n const temp = document.createElement('span');\n temp.innerHTML = newContent;\n // Replace the text node\n parent.replaceChild(temp, firstNode);\n // Unwrap the span if it only contains text\n if (temp.childNodes.length === 1 && temp.firstChild?.nodeType === Node.TEXT_NODE) {\n parent.replaceChild(temp.firstChild, temp);\n }\n }\n }\n } else {\n // No assigned nodes, set innerHTML on the host's light DOM\n this.el.innerHTML = newContent;\n }\n }\n }\n\n /**\n * Handle input in the contenteditable\n */\n private handleInput = () => {\n if (this.editorRef) {\n this.content = this.editorRef.innerHTML;\n this.updateSelectionState();\n }\n };\n\n /**\n * Handle focus on the editor\n */\n private handleFocus = () => {\n this.isFocused = true;\n this.updateSelectionState();\n };\n\n /**\n * Handle blur on the editor\n */\n private handleBlur = (e: FocusEvent) => {\n // Check if focus moved to toolbar\n const relatedTarget = e.relatedTarget as HTMLElement;\n const toolbar = this.el.shadowRoot?.querySelector('.le-text-toolbar');\n\n if (toolbar?.contains(relatedTarget)) {\n // Focus moved to toolbar, keep it open\n return;\n }\n\n // Small delay to allow toolbar clicks to register\n setTimeout(() => {\n if (!this.el.shadowRoot?.activeElement) {\n this.isFocused = false;\n this.syncContentToSlot();\n }\n }, 150);\n };\n\n /**\n * Handle selection change to update toolbar state\n */\n private handleSelectionChange = () => {\n this.updateSelectionState();\n };\n\n /**\n * Update the selection state for toolbar highlighting\n */\n private updateSelectionState() {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n this.selectionState = {\n isBold: document.queryCommandState('bold'),\n isItalic: document.queryCommandState('italic'),\n isUnderline: document.queryCommandState('underline'),\n isStrikethrough: document.queryCommandState('strikeThrough'),\n isLink: this.isSelectionInLink(selection),\n blockType: this.variant,\n };\n }\n\n /**\n * Check if current selection is within a link\n */\n private isSelectionInLink(selection: Selection): boolean {\n if (!selection.anchorNode) return false;\n\n let node: Node | null = selection.anchorNode;\n while (node && node !== this.editorRef) {\n if (node.nodeName === 'A') return true;\n node = node.parentNode;\n }\n return false;\n }\n\n /**\n * Execute a formatting command\n */\n private execCommand(command: string, value?: string) {\n // Focus the editor first\n this.editorRef?.focus();\n\n // Execute the command\n document.execCommand(command, false, value);\n\n // Update state\n this.handleInput();\n this.updateSelectionState();\n }\n\n /**\n * Toggle bold formatting\n */\n private toggleBold = (e: Event) => {\n e.preventDefault();\n this.execCommand('bold');\n };\n\n /**\n * Toggle italic formatting\n */\n private toggleItalic = (e: Event) => {\n e.preventDefault();\n this.execCommand('italic');\n };\n\n /**\n * Toggle underline formatting\n */\n private toggleUnderline = (e: Event) => {\n e.preventDefault();\n this.execCommand('underline');\n };\n\n /**\n * Toggle strikethrough formatting\n */\n private toggleStrikethrough = (e: Event) => {\n e.preventDefault();\n this.execCommand('strikeThrough');\n };\n\n /**\n * Add or edit a link\n */\n private toggleLink = (e: Event) => {\n e.preventDefault();\n\n if (this.selectionState.isLink) {\n // Remove link\n this.execCommand('unlink');\n } else {\n // Add link\n const url = prompt('Enter URL:', 'https://');\n if (url) {\n this.execCommand('createLink', url);\n }\n }\n };\n\n /**\n * Change the block type/variant\n */\n private changeVariant = (e: Event) => {\n const select = e.target as HTMLSelectElement;\n this.variant = select.value as typeof this.variant;\n };\n\n /**\n * Render the formatting toolbar\n */\n private renderToolbar() {\n return (\n <div class=\"le-text-toolbar\">\n <select\n class=\"le-text-toolbar-select\"\n onChange={this.changeVariant}\n onMouseDown={e => e.preventDefault()}\n >\n <option value=\"p\" selected={this.variant === 'p'}>\n Paragraph\n </option>\n <option value=\"h1\" selected={this.variant === 'h1'}>\n Heading 1\n </option>\n <option value=\"h2\" selected={this.variant === 'h2'}>\n Heading 2\n </option>\n <option value=\"h3\" selected={this.variant === 'h3'}>\n Heading 3\n </option>\n <option value=\"h4\" selected={this.variant === 'h4'}>\n Heading 4\n </option>\n <option value=\"h5\" selected={this.variant === 'h5'}>\n Heading 5\n </option>\n <option value=\"h6\" selected={this.variant === 'h6'}>\n Heading 6\n </option>\n <option value=\"quote\" selected={this.variant === 'quote'}>\n Quote\n </option>\n <option value=\"code\" selected={this.variant === 'code'}>\n Code\n </option>\n <option value=\"label\" selected={this.variant === 'label'}>\n Label\n </option>\n <option value=\"small\" selected={this.variant === 'small'}>\n Small\n </option>\n </select>\n\n <div class=\"le-text-toolbar-divider\"></div>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isBold }}\n onMouseDown={this.toggleBold}\n title=\"Bold (Ctrl+B)\"\n >\n <strong>B</strong>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isItalic }}\n onMouseDown={this.toggleItalic}\n title=\"Italic (Ctrl+I)\"\n >\n <em>I</em>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isUnderline }}\n onMouseDown={this.toggleUnderline}\n title=\"Underline (Ctrl+U)\"\n >\n <span style={{ textDecoration: 'underline' }}>U</span>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isStrikethrough }}\n onMouseDown={this.toggleStrikethrough}\n title=\"Strikethrough\"\n >\n <span style={{ textDecoration: 'line-through' }}>S</span>\n </button>\n\n <div class=\"le-text-toolbar-divider\"></div>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isLink }}\n onMouseDown={this.toggleLink}\n title={this.selectionState.isLink ? 'Remove link' : 'Add link'}\n >\n 🔗\n </button>\n </div>\n );\n }\n\n /**\n * Get the semantic tag for the current variant\n */\n private getTag(): string {\n switch (this.variant) {\n case 'quote':\n return 'blockquote';\n case 'code':\n return 'pre';\n case 'label':\n return 'label';\n case 'small':\n return 'small';\n default:\n return this.variant; // h1-h6, p\n }\n }\n\n render() {\n const Tag = this.getTag();\n\n const textStyle: { [key: string]: string } = {};\n if (this.color) {\n textStyle.color = this.color;\n }\n if (this.align) {\n textStyle.textAlign = this.align;\n }\n\n const textClass = {\n 'le-text': true,\n [`variant-${this.variant}`]: true,\n 'truncate': this.truncate,\n [`max-lines-${this.maxLines}`]: this.truncate && this.maxLines,\n };\n\n // Admin mode - show rich text editor\n if (this.adminMode) {\n return (\n <Host class=\"admin-mode\">\n <le-component component=\"le-text\">\n <div class=\"le-text-editor-wrapper\">\n {this.isFocused && this.renderToolbar()}\n <Tag class={textClass} part=\"text\" style={textStyle}>\n <div\n ref={el => (this.editorRef = el)}\n class=\"le-text-editor\"\n contentEditable={true}\n onInput={this.handleInput}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n onKeyUp={this.handleSelectionChange}\n onMouseUp={this.handleSelectionChange}\n innerHTML={this.content}\n ></div>\n </Tag>\n {/* Hidden slot to receive light DOM content */}\n <div class=\"hidden-slot\">\n <slot\n ref={el => (this.slotRef = el as HTMLSlotElement)}\n onSlotchange={() => this.readSlottedContent()}\n ></slot>\n </div>\n </div>\n </le-component>\n </Host>\n );\n }\n\n // Default mode - render semantic element with slotted content\n return (\n <Host>\n <Tag class={textClass} part=\"text\" style={textStyle}>\n <slot ref={el => (this.slotRef = el as HTMLSlotElement)}></slot>\n </Tag>\n </Host>\n );\n }\n}\n\n/**\n * Selection state for toolbar\n */\ninterface SelectionState {\n isBold: boolean;\n isItalic: boolean;\n isUnderline: boolean;\n isStrikethrough: boolean;\n isLink: boolean;\n blockType: string;\n}\n"]}
1
+ {"version":3,"file":"le-text.js","sourceRoot":"","sources":["../../../src/components/le-text/le-text.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Host, Element, Watch } from '@stencil/core';\nimport { observeModeChanges } from '../../utils/utils';\n\n/**\n * A text component with rich text editing capabilities in admin mode.\n *\n * `le-text` renders semantic text elements (headings, paragraphs, code, quotes)\n * and provides a Notion-like rich text editor in admin mode with formatting\n * toolbar for bold, italic, links, and paragraph type selection.\n *\n * @slot - Default slot for text content\n *\n * @cssprop --le-text-color - Text color\n * @cssprop --le-text-font-size - Font size\n * @cssprop --le-text-line-height - Line height\n * @cssprop --le-text-font-weight - Font weight\n *\n * @csspart text - The text container element\n *\n * @cmsEditable true\n * @cmsCategory Content\n */\n@Component({\n tag: 'le-text',\n styleUrl: 'le-text.css',\n shadow: true,\n})\nexport class LeText {\n @Element() el: HTMLElement;\n\n /**\n * The semantic variant/type of text element\n * @allowedValues p | h1 | h2 | h3 | h4 | h5 | h6 | code | quote | label | small\n */\n @Prop({ mutable: true, reflect: true }) variant:\n | 'p'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'code'\n | 'quote'\n | 'label'\n | 'small' = 'p';\n\n /**\n * Text alignment\n * @allowedValues left | center | right | justify\n */\n @Prop({ reflect: true }) align: 'left' | 'center' | 'right' | 'justify' = 'left';\n\n /**\n * Text color (CSS value or theme token)\n */\n @Prop() color?: string;\n\n /**\n * Whether the text should truncate with ellipsis\n */\n @Prop() truncate: boolean = false;\n\n /**\n * Maximum number of lines before truncating (requires truncate=true)\n */\n @Prop() maxLines?: number;\n\n /**\n * Internal state to track admin mode\n */\n @State() private adminMode: boolean = false;\n\n /**\n * The HTML content being edited\n */\n @State() private content: string = '';\n\n /**\n * Whether the editor is focused (shows toolbar)\n */\n @State() private isFocused: boolean = false;\n\n /**\n * Current selection state for toolbar button highlighting\n */\n @State() private selectionState: SelectionState = {\n isBold: false,\n isItalic: false,\n isUnderline: false,\n isStrikethrough: false,\n isLink: false,\n blockType: 'p',\n };\n\n /**\n * Reference to the contenteditable element\n */\n private editorRef?: HTMLDivElement;\n\n /**\n * Reference to the slot element\n */\n private slotRef?: HTMLSlotElement;\n\n private disconnectModeObserver?: () => void;\n\n connectedCallback() {\n this.disconnectModeObserver = observeModeChanges(this.el, mode => {\n const wasAdmin = this.adminMode;\n this.adminMode = mode === 'admin';\n\n if (this.adminMode && !wasAdmin) {\n // Entering admin mode - read content from slot\n requestAnimationFrame(() => this.readSlottedContent());\n } else if (!this.adminMode && wasAdmin) {\n // Leaving admin mode - sync content back to slot\n this.syncContentToSlot();\n }\n });\n }\n\n disconnectedCallback() {\n this.disconnectModeObserver?.();\n }\n\n @Watch('variant')\n onVariantChange() {\n // When variant changes in admin mode, update the content wrapper\n if (this.adminMode && this.editorRef) {\n this.syncContentToSlot();\n }\n }\n\n /**\n * Read content from slotted elements\n */\n private readSlottedContent() {\n if (!this.slotRef) return;\n\n const assignedNodes = this.slotRef.assignedNodes({ flatten: true });\n\n // Collect all content from assigned nodes\n let html = '';\n assignedNodes.forEach(node => {\n if (node.nodeType === Node.TEXT_NODE) {\n html += node.textContent;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n html += (node as Element).innerHTML || node.textContent;\n }\n });\n\n this.content = html.trim();\n }\n\n /**\n * Sync edited content back to the slot\n */\n private syncContentToSlot() {\n if (!this.editorRef) return;\n\n const newContent = this.editorRef.innerHTML;\n\n // Update the light DOM content\n // We need to update the actual slotted content\n const slot = this.slotRef;\n if (slot) {\n const assignedNodes = slot.assignedNodes({ flatten: true });\n if (assignedNodes.length > 0) {\n const firstNode = assignedNodes[0];\n if (firstNode.nodeType === Node.ELEMENT_NODE) {\n (firstNode as Element).innerHTML = newContent;\n } else if (firstNode.nodeType === Node.TEXT_NODE) {\n // Replace text node with the new content\n const parent = firstNode.parentNode;\n if (parent) {\n // Create a temporary element to parse HTML\n const temp = document.createElement('span');\n temp.innerHTML = newContent;\n // Replace the text node\n parent.replaceChild(temp, firstNode);\n // Unwrap the span if it only contains text\n if (temp.childNodes.length === 1 && temp.firstChild?.nodeType === Node.TEXT_NODE) {\n parent.replaceChild(temp.firstChild, temp);\n }\n }\n }\n } else {\n // No assigned nodes, set innerHTML on the host's light DOM\n this.el.innerHTML = newContent;\n }\n }\n }\n\n /**\n * Handle input in the contenteditable\n */\n private handleInput = () => {\n if (this.editorRef) {\n this.content = this.editorRef.innerHTML;\n this.updateSelectionState();\n }\n };\n\n /**\n * Handle focus on the editor\n */\n private handleFocus = () => {\n this.isFocused = true;\n this.updateSelectionState();\n };\n\n /**\n * Handle blur on the editor\n */\n private handleBlur = (e: FocusEvent) => {\n // Check if focus moved to toolbar\n const relatedTarget = e.relatedTarget as HTMLElement;\n const toolbar = this.el.shadowRoot?.querySelector('.le-text-toolbar');\n\n if (toolbar?.contains(relatedTarget)) {\n // Focus moved to toolbar, keep it open\n return;\n }\n\n // Small delay to allow toolbar clicks to register\n setTimeout(() => {\n if (!this.el.shadowRoot?.activeElement) {\n this.isFocused = false;\n this.syncContentToSlot();\n }\n }, 150);\n };\n\n /**\n * Handle selection change to update toolbar state\n */\n private handleSelectionChange = () => {\n this.updateSelectionState();\n };\n\n /**\n * Update the selection state for toolbar highlighting\n */\n private updateSelectionState() {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n this.selectionState = {\n isBold: document.queryCommandState('bold'),\n isItalic: document.queryCommandState('italic'),\n isUnderline: document.queryCommandState('underline'),\n isStrikethrough: document.queryCommandState('strikeThrough'),\n isLink: this.isSelectionInLink(selection),\n blockType: this.variant,\n };\n }\n\n /**\n * Check if current selection is within a link\n */\n private isSelectionInLink(selection: Selection): boolean {\n if (!selection.anchorNode) return false;\n\n let node: Node | null = selection.anchorNode;\n while (node && node !== this.editorRef) {\n if (node.nodeName === 'A') return true;\n node = node.parentNode;\n }\n return false;\n }\n\n /**\n * Execute a formatting command\n */\n private execCommand(command: string, value?: string) {\n // Focus the editor first\n this.editorRef?.focus();\n\n // Execute the command\n document.execCommand(command, false, value);\n\n // Update state\n this.handleInput();\n this.updateSelectionState();\n }\n\n /**\n * Toggle bold formatting\n */\n private toggleBold = (e: Event) => {\n e.preventDefault();\n this.execCommand('bold');\n };\n\n /**\n * Toggle italic formatting\n */\n private toggleItalic = (e: Event) => {\n e.preventDefault();\n this.execCommand('italic');\n };\n\n /**\n * Toggle underline formatting\n */\n private toggleUnderline = (e: Event) => {\n e.preventDefault();\n this.execCommand('underline');\n };\n\n /**\n * Toggle strikethrough formatting\n */\n private toggleStrikethrough = (e: Event) => {\n e.preventDefault();\n this.execCommand('strikeThrough');\n };\n\n /**\n * Add or edit a link\n */\n private toggleLink = (e: Event) => {\n e.preventDefault();\n\n if (this.selectionState.isLink) {\n // Remove link\n this.execCommand('unlink');\n } else {\n // Add link\n const url = prompt('Enter URL:', 'https://');\n if (url) {\n this.execCommand('createLink', url);\n }\n }\n };\n\n /**\n * Change the block type/variant\n */\n private changeVariant = (e: Event) => {\n const select = e.target as HTMLSelectElement;\n this.variant = select.value as typeof this.variant;\n };\n\n /**\n * Render the formatting toolbar\n */\n private renderToolbar() {\n return (\n <div class=\"le-text-toolbar\">\n <select\n class=\"le-text-toolbar-select\"\n onChange={this.changeVariant}\n onMouseDown={e => e.preventDefault()}\n >\n <option value=\"p\" selected={this.variant === 'p'}>\n Paragraph\n </option>\n <option value=\"h1\" selected={this.variant === 'h1'}>\n Heading 1\n </option>\n <option value=\"h2\" selected={this.variant === 'h2'}>\n Heading 2\n </option>\n <option value=\"h3\" selected={this.variant === 'h3'}>\n Heading 3\n </option>\n <option value=\"h4\" selected={this.variant === 'h4'}>\n Heading 4\n </option>\n <option value=\"h5\" selected={this.variant === 'h5'}>\n Heading 5\n </option>\n <option value=\"h6\" selected={this.variant === 'h6'}>\n Heading 6\n </option>\n <option value=\"quote\" selected={this.variant === 'quote'}>\n Quote\n </option>\n <option value=\"code\" selected={this.variant === 'code'}>\n Code\n </option>\n <option value=\"label\" selected={this.variant === 'label'}>\n Label\n </option>\n <option value=\"small\" selected={this.variant === 'small'}>\n Small\n </option>\n </select>\n\n <div class=\"le-text-toolbar-divider\"></div>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isBold }}\n onMouseDown={this.toggleBold}\n title=\"Bold (Ctrl+B)\"\n >\n <strong>B</strong>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isItalic }}\n onMouseDown={this.toggleItalic}\n title=\"Italic (Ctrl+I)\"\n >\n <em>I</em>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isUnderline }}\n onMouseDown={this.toggleUnderline}\n title=\"Underline (Ctrl+U)\"\n >\n <span style={{ textDecoration: 'underline' }}>U</span>\n </button>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isStrikethrough }}\n onMouseDown={this.toggleStrikethrough}\n title=\"Strikethrough\"\n >\n <span style={{ textDecoration: 'line-through' }}>S</span>\n </button>\n\n <div class=\"le-text-toolbar-divider\"></div>\n\n <button\n type=\"button\"\n class={{ 'le-text-toolbar-btn': true, 'active': this.selectionState.isLink }}\n onMouseDown={this.toggleLink}\n title={this.selectionState.isLink ? 'Remove link' : 'Add link'}\n >\n 🔗\n </button>\n </div>\n );\n }\n\n /**\n * Get the semantic tag for the current variant\n */\n private getTag(): string {\n switch (this.variant) {\n case 'quote':\n return 'blockquote';\n case 'code':\n return 'pre';\n case 'label':\n return 'label';\n case 'small':\n return 'small';\n default:\n return this.variant; // h1-h6, p\n }\n }\n\n render() {\n const Tag = this.getTag();\n\n const textStyle: { [key: string]: string } = {};\n if (this.color) {\n textStyle.color = this.color;\n }\n if (this.align) {\n textStyle.textAlign = this.align;\n }\n\n const textClass = {\n 'le-text': true,\n [`variant-${this.variant}`]: true,\n 'truncate': this.truncate,\n [`max-lines-${this.maxLines}`]: this.truncate && this.maxLines,\n };\n\n // Admin mode - show rich text editor\n if (this.adminMode) {\n return (\n <Host class=\"admin-mode\">\n <le-component component=\"le-text\">\n <div class=\"le-text-editor-wrapper\">\n {this.isFocused && this.renderToolbar()}\n <Tag class={textClass} part=\"text\" style={textStyle}>\n <div\n ref={el => (this.editorRef = el)}\n class=\"le-text-editor\"\n contentEditable={true}\n onInput={this.handleInput}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n onKeyUp={this.handleSelectionChange}\n onMouseUp={this.handleSelectionChange}\n innerHTML={this.content}\n ></div>\n </Tag>\n {/* Hidden slot to receive light DOM content */}\n <div class=\"hidden-slot\">\n <slot\n ref={el => (this.slotRef = el as HTMLSlotElement)}\n onSlotchange={() => this.readSlottedContent()}\n ></slot>\n </div>\n </div>\n </le-component>\n </Host>\n );\n }\n\n // Default mode - render semantic element with slotted content\n return (\n <Host>\n <Tag class={textClass} part=\"text\" style={textStyle}>\n <slot ref={el => (this.slotRef = el as HTMLSlotElement)}></slot>\n </Tag>\n </Host>\n );\n }\n}\n\n/**\n * Selection state for toolbar\n */\ninterface SelectionState {\n isBold: boolean;\n isItalic: boolean;\n isUnderline: boolean;\n isStrikethrough: boolean;\n isLink: boolean;\n blockType: string;\n}\n"]}
@@ -1,36 +1,28 @@
1
1
  import { h } from "@stencil/core";
2
2
  export class LeTurntable {
3
- // host element
4
- el;
5
- // transform origin
6
- // gets the same values as transform-origin css property
7
- center = 'center';
8
- // transform rotate
9
- value = 0;
3
+ constructor() {
4
+ // transform origin
5
+ // gets the same values as transform-origin css property
6
+ this.center = 'center';
7
+ // transform rotate
8
+ this.value = 0;
9
+ /**
10
+ * Internal state
11
+ *
12
+ * using properties instead of @State decoratorm
13
+ * because we are only changing styles of the element and don't
14
+ * need the element to be rerendered
15
+ */
16
+ // indicates is the element being manually rotated right now
17
+ this.rotating = false;
18
+ this.currentAngle = 0;
19
+ }
10
20
  updateValue(newValue) {
11
21
  if (!this.rotating) {
12
22
  this.currentAngle = parseFloat(newValue);
13
23
  this.setAngle(this.currentAngle);
14
24
  }
15
25
  }
16
- /**
17
- * Internal state
18
- *
19
- * using properties instead of @State decoratorm
20
- * because we are only changing styles of the element and don't
21
- * need the element to be rerendered
22
- */
23
- // indicates is the element being manually rotated right now
24
- rotating = false;
25
- // coordinates of the transform origin in pixels
26
- centerX;
27
- centerY;
28
- // element page (body?) offset in pixels
29
- pageX;
30
- pageY;
31
- currentAngle = 0;
32
- // angle at the start of the drag
33
- startAngle;
34
26
  /**
35
27
  * Event listeners
36
28
  */
@@ -120,7 +112,7 @@ export class LeTurntable {
120
112
  this.el.style.transform = `rotate(${angle}deg)`;
121
113
  }
122
114
  render() {
123
- return (h("div", { key: '50d1e3a01db9e77a3c391e04af74b70f39c23f8f', class: "turntable", onMouseDown: this.handleMouseDown.bind(this) }, h("slot", { key: 'a4c5d3cc2a99edf860ff7aa5318fa76443cdd2fd' })));
115
+ return (h("div", { key: 'c3708c547602a5c0886d3e8d01e1393703f9dbd7', class: "turntable", onMouseDown: this.handleMouseDown.bind(this) }, h("slot", { key: 'f124aeded59878dec8e7b9def2047c4381864994' })));
124
116
  }
125
117
  static get is() { return "le-turntable"; }
126
118
  static get encapsulation() { return "shadow"; }
@@ -1 +1 @@
1
- {"version":3,"file":"le-turntable.js","sourceRoot":"","sources":["../../../src/components/le-turntable/le-turntable.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Element, Prop, Listen, h, Watch } from '@stencil/core';\n\n@Component({\n tag: 'le-turntable',\n styleUrl: 'le-turntable.css',\n shadow: true,\n})\nexport class LeTurntable {\n // host element\n @Element() el: HTMLElement;\n\n // transform origin\n // gets the same values as transform-origin css property\n @Prop() center: string = 'center';\n\n // transform rotate\n @Prop() value: number = 0;\n\n @Watch('value')\n updateValue(newValue) {\n if (!this.rotating) {\n this.currentAngle = parseFloat(newValue);\n this.setAngle(this.currentAngle);\n }\n }\n\n /**\n * Internal state\n *\n * using properties instead of @State decoratorm\n * because we are only changing styles of the element and don't\n * need the element to be rerendered\n */\n\n // indicates is the element being manually rotated right now\n rotating = false;\n\n // coordinates of the transform origin in pixels\n centerX: number;\n centerY: number;\n\n // element page (body?) offset in pixels\n pageX: number;\n pageY: number;\n\n currentAngle: number = 0;\n // angle at the start of the drag\n startAngle: number;\n\n /**\n * Event listeners\n */\n handleMouseDown(evt: MouseEvent) {\n // set rotating mode on\n this.rotating = true;\n\n // get start angle\n // getting pageX/Y, because when the element is transformed\n // relative values are useless\n this.startAngle = this.getAngle(evt.pageX, evt.pageY);\n\n // cancel the event to prevent text selection\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n }\n\n /**\n * Fires when the mouse moves\n * checks is the element rotating right now and if it is\n * then calc the current angle and rotate the element\n *\n * TODO: attach events only after the dragStart?\n */\n @Listen('mousemove', { target: 'window' })\n handleMouseMove(evt: MouseEvent) {\n if (this.rotating) {\n // calc angle update and rotate element\n this.setAngle(this.currentAngle + (this.getAngle(evt.pageX, evt.pageY) - this.startAngle));\n return false;\n }\n }\n\n @Listen('mouseup', { target: 'window' })\n handleMouseUp(evt: MouseEvent) {\n if (this.rotating) {\n const angle = this.currentAngle + (this.getAngle(evt.pageX, evt.pageY) - this.startAngle);\n this.setAngle(angle);\n this.currentAngle = angle;\n this.rotating = false;\n return false;\n }\n }\n\n // on window resize the center should be recalculated\n @Listen('resize', { target: 'window' })\n handleWindowResize() {\n this.getTransformOrigin();\n }\n\n /**\n * Component lifecycles\n */\n componentDidLoad() {\n this.el.style.transformOrigin = this.center;\n this.currentAngle = this.value;\n\n this.getTransformOrigin();\n this.setAngle(this.currentAngle);\n }\n\n componentDidUpdate() {\n this.getTransformOrigin();\n }\n\n /**\n * Calculates the transform origin of the component\n * and the page offset in pixels\n *\n * We'll need these values to calculate the angle of pointer event\n */\n getTransformOrigin() {\n // transform origin\n [this.centerX, this.centerY] = window\n .getComputedStyle(this.el, null)\n .transformOrigin.split(' ')\n .map(val => Math.round(parseFloat(val)));\n // page offset\n let t = null;\n const scrollContainer = ((t = document.documentElement) || (t = document.body.parentNode)) && typeof t.scrollLeft === 'number' ? t : document.body;\n const clientRects = this.el.getBoundingClientRect();\n this.pageX = Math.round(clientRects.left + scrollContainer.scrollLeft);\n this.pageY = Math.round(clientRects.top + scrollContainer.scrollTop);\n }\n\n /**\n * Calculates current angle\n *\n * @param {number} posX horizontal mouse position\n * @param {number} posY vertical mouse position\n */\n getAngle(posX: number, posY: number) {\n const x = posX - this.pageX - this.centerX;\n const y = posY - this.pageY - this.centerY;\n const angle = Math.round(((Math.atan2(y, x) * 180) / Math.PI) * 100) / 100;\n return angle;\n }\n\n setAngle(angle) {\n this.el.style.transform = `rotate(${angle}deg)`;\n }\n\n render() {\n return (\n <div class=\"turntable\" onMouseDown={this.handleMouseDown.bind(this)}>\n <slot />\n </div>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"le-turntable.js","sourceRoot":"","sources":["../../../src/components/le-turntable/le-turntable.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Element, Prop, Listen, h, Watch } from '@stencil/core';\n\n@Component({\n tag: 'le-turntable',\n styleUrl: 'le-turntable.css',\n shadow: true,\n})\nexport class LeTurntable {\n // host element\n @Element() el: HTMLElement;\n\n // transform origin\n // gets the same values as transform-origin css property\n @Prop() center: string = 'center';\n\n // transform rotate\n @Prop() value: number = 0;\n\n @Watch('value')\n updateValue(newValue) {\n if (!this.rotating) {\n this.currentAngle = parseFloat(newValue);\n this.setAngle(this.currentAngle);\n }\n }\n\n /**\n * Internal state\n *\n * using properties instead of @State decoratorm\n * because we are only changing styles of the element and don't\n * need the element to be rerendered\n */\n\n // indicates is the element being manually rotated right now\n rotating = false;\n\n // coordinates of the transform origin in pixels\n centerX: number;\n centerY: number;\n\n // element page (body?) offset in pixels\n pageX: number;\n pageY: number;\n\n currentAngle: number = 0;\n // angle at the start of the drag\n startAngle: number;\n\n /**\n * Event listeners\n */\n handleMouseDown(evt: MouseEvent) {\n // set rotating mode on\n this.rotating = true;\n\n // get start angle\n // getting pageX/Y, because when the element is transformed\n // relative values are useless\n this.startAngle = this.getAngle(evt.pageX, evt.pageY);\n\n // cancel the event to prevent text selection\n evt.preventDefault();\n evt.stopPropagation();\n return false;\n }\n\n /**\n * Fires when the mouse moves\n * checks is the element rotating right now and if it is\n * then calc the current angle and rotate the element\n *\n * TODO: attach events only after the dragStart?\n */\n @Listen('mousemove', { target: 'window' })\n handleMouseMove(evt: MouseEvent) {\n if (this.rotating) {\n // calc angle update and rotate element\n this.setAngle(this.currentAngle + (this.getAngle(evt.pageX, evt.pageY) - this.startAngle));\n return false;\n }\n }\n\n @Listen('mouseup', { target: 'window' })\n handleMouseUp(evt: MouseEvent) {\n if (this.rotating) {\n const angle = this.currentAngle + (this.getAngle(evt.pageX, evt.pageY) - this.startAngle);\n this.setAngle(angle);\n this.currentAngle = angle;\n this.rotating = false;\n return false;\n }\n }\n\n // on window resize the center should be recalculated\n @Listen('resize', { target: 'window' })\n handleWindowResize() {\n this.getTransformOrigin();\n }\n\n /**\n * Component lifecycles\n */\n componentDidLoad() {\n this.el.style.transformOrigin = this.center;\n this.currentAngle = this.value;\n\n this.getTransformOrigin();\n this.setAngle(this.currentAngle);\n }\n\n componentDidUpdate() {\n this.getTransformOrigin();\n }\n\n /**\n * Calculates the transform origin of the component\n * and the page offset in pixels\n *\n * We'll need these values to calculate the angle of pointer event\n */\n getTransformOrigin() {\n // transform origin\n [this.centerX, this.centerY] = window\n .getComputedStyle(this.el, null)\n .transformOrigin.split(' ')\n .map(val => Math.round(parseFloat(val)));\n // page offset\n let t = null;\n const scrollContainer = ((t = document.documentElement) || (t = document.body.parentNode)) && typeof t.scrollLeft === 'number' ? t : document.body;\n const clientRects = this.el.getBoundingClientRect();\n this.pageX = Math.round(clientRects.left + scrollContainer.scrollLeft);\n this.pageY = Math.round(clientRects.top + scrollContainer.scrollTop);\n }\n\n /**\n * Calculates current angle\n *\n * @param {number} posX horizontal mouse position\n * @param {number} posY vertical mouse position\n */\n getAngle(posX: number, posY: number) {\n const x = posX - this.pageX - this.centerX;\n const y = posY - this.pageY - this.centerY;\n const angle = Math.round(((Math.atan2(y, x) * 180) / Math.PI) * 100) / 100;\n return angle;\n }\n\n setAngle(angle) {\n this.el.style.transform = `rotate(${angle}deg)`;\n }\n\n render() {\n return (\n <div class=\"turntable\" onMouseDown={this.handleMouseDown.bind(this)}>\n <slot />\n </div>\n );\n }\n}\n"]}