le-kit 0.1.15 → 0.1.16

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 (235) hide show
  1. package/dist/cjs/{index-C3iQZ-Ja.js → index-CHzu3ydp.js} +3 -3
  2. package/dist/cjs/index-CHzu3ydp.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +2 -2
  4. package/dist/cjs/le-box.cjs.entry.js +2 -2
  5. package/dist/cjs/le-button.le-checkbox.le-collapse.le-component.le-current-heading.le-dropdown-base.le-header.le-popover.le-popup.le-scroll-progress.le-select.le-slot.le-string-input.entry.cjs.js.map +1 -0
  6. package/dist/cjs/{le-button_7.cjs.entry.js → le-button_13.cjs.entry.js} +1148 -21
  7. package/dist/cjs/le-card.cjs.entry.js +2 -2
  8. package/dist/cjs/le-combobox.cjs.entry.js +2 -2
  9. package/dist/cjs/le-header-placeholder.cjs.entry.js +18 -0
  10. package/dist/cjs/le-header-placeholder.entry.cjs.js.map +1 -0
  11. package/dist/cjs/le-kit.cjs.js +2 -2
  12. package/dist/cjs/le-multiselect.cjs.entry.js +4 -4
  13. package/dist/cjs/le-number-input.cjs.entry.js +3 -3
  14. package/dist/cjs/le-round-progress.cjs.entry.js +2 -2
  15. package/dist/cjs/le-segmented-control.cjs.entry.js +2 -2
  16. package/dist/cjs/le-stack.cjs.entry.js +3 -3
  17. package/dist/cjs/le-tab-bar.cjs.entry.js +2 -2
  18. package/dist/cjs/le-tab-panel.cjs.entry.js +3 -3
  19. package/dist/cjs/le-tab.cjs.entry.js +3 -3
  20. package/dist/cjs/le-tabs.cjs.entry.js +4 -4
  21. package/dist/cjs/le-tag.cjs.entry.js +2 -2
  22. package/dist/cjs/le-text.cjs.entry.js +2 -2
  23. package/dist/cjs/le-turntable.cjs.entry.js +2 -2
  24. package/dist/cjs/loader.cjs.js +2 -2
  25. package/dist/cjs/{utils-DjPcLPN9.js → utils-CYOKcOW8.js} +3 -3
  26. package/dist/cjs/{utils-DjPcLPN9.js.map → utils-CYOKcOW8.js.map} +1 -1
  27. package/dist/collection/collection-manifest.json +5 -0
  28. package/dist/collection/components/le-collapse/le-collapse.css +31 -0
  29. package/dist/collection/components/le-collapse/le-collapse.js +188 -0
  30. package/dist/collection/components/le-collapse/le-collapse.js.map +1 -0
  31. package/dist/collection/components/le-combobox/le-combobox.js +1 -1
  32. package/dist/collection/components/le-component/le-component.js +1 -1
  33. package/dist/collection/components/le-component/le-component.js.map +1 -1
  34. package/dist/collection/components/le-current-heading/le-current-heading.css +12 -0
  35. package/dist/collection/components/le-current-heading/le-current-heading.js +130 -0
  36. package/dist/collection/components/le-current-heading/le-current-heading.js.map +1 -0
  37. package/dist/collection/components/le-dropdown-base/le-dropdown-base.css +4 -0
  38. package/dist/collection/components/le-dropdown-base/le-dropdown-base.js +1 -1
  39. package/dist/collection/components/le-header/le-header.css +120 -0
  40. package/dist/collection/components/le-header/le-header.js +508 -0
  41. package/dist/collection/components/le-header/le-header.js.map +1 -0
  42. package/dist/collection/components/le-header-placeholder/le-header-placeholder.js +21 -0
  43. package/dist/collection/components/le-header-placeholder/le-header-placeholder.js.map +1 -0
  44. package/dist/collection/components/le-multiselect/le-multiselect.js +3 -3
  45. package/dist/collection/components/le-number-input/le-number-input.js +1 -1
  46. package/dist/collection/components/le-popover/le-popover.css +10 -0
  47. package/dist/collection/components/le-popover/le-popover.js +122 -13
  48. package/dist/collection/components/le-popover/le-popover.js.map +1 -1
  49. package/dist/collection/components/le-round-progress/le-round-progress.js +1 -1
  50. package/dist/collection/components/le-scroll-progress/le-scroll-progress.css +29 -0
  51. package/dist/collection/components/le-scroll-progress/le-scroll-progress.js +186 -0
  52. package/dist/collection/components/le-scroll-progress/le-scroll-progress.js.map +1 -0
  53. package/dist/collection/components/le-segmented-control/le-segmented-control.js +1 -1
  54. package/dist/collection/components/le-select/le-select.js +2 -2
  55. package/dist/collection/components/le-slot/le-slot.js +1 -1
  56. package/dist/collection/components/le-stack/le-stack.js +1 -1
  57. package/dist/collection/components/le-string-input/le-string-input.js +2 -2
  58. package/dist/collection/components/le-tab/le-tab.js +1 -1
  59. package/dist/collection/components/le-tab-bar/le-tab-bar.js +1 -1
  60. package/dist/collection/components/le-tab-panel/le-tab-panel.js +2 -2
  61. package/dist/collection/components/le-tabs/le-tabs.js +2 -2
  62. package/dist/collection/components/le-tag/le-tag.js +1 -1
  63. package/dist/collection/components/le-turntable/le-turntable.js +1 -1
  64. package/dist/collection/dist/components/assets/custom-elements.json +2029 -965
  65. package/dist/collection/dist/components/themes/base.css +4 -48
  66. package/dist/collection/dist/components/themes/index.css +3 -342
  67. package/dist/components/assets/custom-elements.json +2029 -965
  68. package/dist/components/index.js.map +1 -1
  69. package/dist/components/le-box.js +18 -7
  70. package/dist/components/le-box.js.map +1 -1
  71. package/dist/components/le-button.js +1 -1
  72. package/dist/components/le-button2.js +331 -31
  73. package/dist/components/le-button2.js.map +1 -1
  74. package/dist/components/le-card.js +18 -7
  75. package/dist/components/le-card.js.map +1 -1
  76. package/dist/components/le-checkbox.js +1 -1
  77. package/dist/components/le-collapse.d.ts +11 -0
  78. package/dist/components/le-collapse.js +144 -0
  79. package/dist/components/le-collapse.js.map +1 -0
  80. package/dist/components/le-combobox.js +15 -10
  81. package/dist/components/le-combobox.js.map +1 -1
  82. package/dist/components/le-component.js +1 -1
  83. package/dist/components/le-current-heading.d.ts +11 -0
  84. package/dist/components/le-current-heading.js +93 -0
  85. package/dist/components/le-current-heading.js.map +1 -0
  86. package/dist/components/le-dropdown-base2.js +2 -2
  87. package/dist/components/le-dropdown-base2.js.map +1 -1
  88. package/dist/components/le-header-placeholder.d.ts +11 -0
  89. package/dist/components/le-header-placeholder.js +37 -0
  90. package/dist/components/le-header-placeholder.js.map +1 -0
  91. package/dist/components/le-header.d.ts +11 -0
  92. package/dist/components/le-header.js +347 -0
  93. package/dist/components/le-header.js.map +1 -0
  94. package/dist/components/le-multiselect.js +17 -12
  95. package/dist/components/le-multiselect.js.map +1 -1
  96. package/dist/components/le-number-input.js +19 -8
  97. package/dist/components/le-number-input.js.map +1 -1
  98. package/dist/components/le-popover2.js +123 -14
  99. package/dist/components/le-popover2.js.map +1 -1
  100. package/dist/components/le-popup.js +1 -1
  101. package/dist/components/le-round-progress.js +1 -1
  102. package/dist/components/le-scroll-progress.d.ts +11 -0
  103. package/dist/components/le-scroll-progress.js +142 -0
  104. package/dist/components/le-scroll-progress.js.map +1 -0
  105. package/dist/components/le-segmented-control.js +19 -8
  106. package/dist/components/le-segmented-control.js.map +1 -1
  107. package/dist/components/le-select.js +1 -263
  108. package/dist/components/le-select.js.map +1 -1
  109. package/dist/components/le-slot.js +1 -1
  110. package/dist/components/le-stack.js +19 -8
  111. package/dist/components/le-stack.js.map +1 -1
  112. package/dist/components/le-string-input.js +1 -1
  113. package/dist/components/le-tab-bar.js +19 -8
  114. package/dist/components/le-tab-bar.js.map +1 -1
  115. package/dist/components/le-tab-panel.js +20 -9
  116. package/dist/components/le-tab-panel.js.map +1 -1
  117. package/dist/components/le-tab2.js +19 -8
  118. package/dist/components/le-tab2.js.map +1 -1
  119. package/dist/components/le-tabs.js +20 -9
  120. package/dist/components/le-tabs.js.map +1 -1
  121. package/dist/components/le-tag2.js +19 -8
  122. package/dist/components/le-tag2.js.map +1 -1
  123. package/dist/components/le-text.js +18 -7
  124. package/dist/components/le-text.js.map +1 -1
  125. package/dist/components/le-turntable.js +1 -1
  126. package/dist/components/themes/base.css +4 -48
  127. package/dist/components/themes/index.css +3 -342
  128. package/dist/docs.json +1089 -30
  129. package/dist/esm/{index-DzgCnDLJ.js → index-hmBwv43R.js} +3 -3
  130. package/dist/esm/index-hmBwv43R.js.map +1 -0
  131. package/dist/esm/index.js +2 -2
  132. package/dist/esm/le-box.entry.js +2 -2
  133. package/dist/esm/le-button.le-checkbox.le-collapse.le-component.le-current-heading.le-dropdown-base.le-header.le-popover.le-popup.le-scroll-progress.le-select.le-slot.le-string-input.entry.js.map +1 -0
  134. package/dist/esm/{le-button_7.entry.js → le-button_13.entry.js} +1143 -22
  135. package/dist/esm/le-card.entry.js +2 -2
  136. package/dist/esm/le-combobox.entry.js +2 -2
  137. package/dist/esm/le-header-placeholder.entry.js +16 -0
  138. package/dist/esm/le-header-placeholder.entry.js.map +1 -0
  139. package/dist/esm/le-kit.js +3 -3
  140. package/dist/esm/le-multiselect.entry.js +4 -4
  141. package/dist/esm/le-number-input.entry.js +3 -3
  142. package/dist/esm/le-round-progress.entry.js +2 -2
  143. package/dist/esm/le-segmented-control.entry.js +2 -2
  144. package/dist/esm/le-stack.entry.js +3 -3
  145. package/dist/esm/le-tab-bar.entry.js +2 -2
  146. package/dist/esm/le-tab-panel.entry.js +3 -3
  147. package/dist/esm/le-tab.entry.js +3 -3
  148. package/dist/esm/le-tabs.entry.js +4 -4
  149. package/dist/esm/le-tag.entry.js +2 -2
  150. package/dist/esm/le-text.entry.js +2 -2
  151. package/dist/esm/le-turntable.entry.js +2 -2
  152. package/dist/esm/loader.js +3 -3
  153. package/dist/esm/{utils-Dp5xFMCl.js → utils-DRTFlnxz.js} +3 -3
  154. package/dist/esm/{utils-Dp5xFMCl.js.map → utils-DRTFlnxz.js.map} +1 -1
  155. package/dist/le-kit/dist/components/assets/custom-elements.json +2029 -965
  156. package/dist/le-kit/dist/components/themes/base.css +4 -48
  157. package/dist/le-kit/dist/components/themes/index.css +3 -342
  158. package/dist/le-kit/index.esm.js +1 -1
  159. package/dist/le-kit/le-button.le-checkbox.le-collapse.le-component.le-current-heading.le-dropdown-base.le-header.le-popover.le-popup.le-scroll-progress.le-select.le-slot.le-string-input.entry.esm.js.map +1 -0
  160. package/dist/le-kit/le-header-placeholder.entry.esm.js.map +1 -0
  161. package/dist/le-kit/le-kit.css +1 -1
  162. package/dist/le-kit/le-kit.esm.js +1 -1
  163. package/dist/le-kit/{p-1f55a4a2.entry.js → p-13a4dc1d.entry.js} +2 -2
  164. package/dist/le-kit/{p-0bd7803f.entry.js → p-1a9e65d0.entry.js} +2 -2
  165. package/dist/le-kit/p-2708dc65.entry.js +2 -0
  166. package/dist/le-kit/p-2708dc65.entry.js.map +1 -0
  167. package/dist/le-kit/p-2b96a5bd.entry.js +2 -0
  168. package/dist/le-kit/p-2b96a5bd.entry.js.map +1 -0
  169. package/dist/le-kit/{p-7b180d58.entry.js → p-32cbb683.entry.js} +2 -2
  170. package/dist/le-kit/{p-71c78784.entry.js → p-476e1886.entry.js} +2 -2
  171. package/dist/le-kit/p-67d702f9.entry.js +2 -0
  172. package/dist/le-kit/{p-33612923.entry.js → p-6884e3e8.entry.js} +2 -2
  173. package/dist/le-kit/{p-6ecdad85.entry.js → p-704ad5e0.entry.js} +2 -2
  174. package/dist/le-kit/{p-432e8231.entry.js → p-88f9aa40.entry.js} +2 -2
  175. package/dist/le-kit/{p-91993261.entry.js → p-8dd8a487.entry.js} +2 -2
  176. package/dist/le-kit/{p-6ee06c44.entry.js → p-97b7658a.entry.js} +2 -2
  177. package/dist/le-kit/{p-a5d31d40.entry.js → p-c0925e92.entry.js} +2 -2
  178. package/dist/le-kit/{p-548d130b.entry.js → p-c2494a0d.entry.js} +2 -2
  179. package/dist/le-kit/{p-3a52c4de.entry.js → p-ded51018.entry.js} +2 -2
  180. package/dist/le-kit/{p-2c37f174.entry.js → p-e3db7974.entry.js} +2 -2
  181. package/dist/le-kit/{p-b66fd9e1.entry.js → p-f9b03aec.entry.js} +2 -2
  182. package/dist/le-kit/p-hmBwv43R.js +3 -0
  183. package/dist/le-kit/p-hmBwv43R.js.map +1 -0
  184. package/dist/le-kit/p-txKmCJHv.js +2 -0
  185. package/dist/le-kit/{p-DaA5gINj.js.map → p-txKmCJHv.js.map} +1 -1
  186. package/dist/themes/base.css +4 -48
  187. package/dist/themes/index.css +3 -342
  188. package/dist/types/components/le-collapse/le-collapse.d.ts +41 -0
  189. package/dist/types/components/le-current-heading/le-current-heading.d.ts +25 -0
  190. package/dist/types/components/le-header/le-header.d.ts +115 -0
  191. package/dist/types/components/le-header-placeholder/le-header-placeholder.d.ts +13 -0
  192. package/dist/types/components/le-popover/le-popover.d.ts +9 -0
  193. package/dist/types/components/le-scroll-progress/le-scroll-progress.d.ts +40 -0
  194. package/dist/types/components.d.ts +518 -0
  195. package/package.json +1 -1
  196. package/dist/cjs/index-C3iQZ-Ja.js.map +0 -1
  197. package/dist/cjs/le-button.le-checkbox.le-component.le-popover.le-popup.le-slot.le-string-input.entry.cjs.js.map +0 -1
  198. package/dist/cjs/le-dropdown-base.cjs.entry.js +0 -348
  199. package/dist/cjs/le-dropdown-base.entry.cjs.js.map +0 -1
  200. package/dist/cjs/le-select.cjs.entry.js +0 -188
  201. package/dist/cjs/le-select.entry.cjs.js.map +0 -1
  202. package/dist/esm/index-DzgCnDLJ.js.map +0 -1
  203. package/dist/esm/le-button.le-checkbox.le-component.le-popover.le-popup.le-slot.le-string-input.entry.js.map +0 -1
  204. package/dist/esm/le-dropdown-base.entry.js +0 -346
  205. package/dist/esm/le-dropdown-base.entry.js.map +0 -1
  206. package/dist/esm/le-select.entry.js +0 -186
  207. package/dist/esm/le-select.entry.js.map +0 -1
  208. package/dist/le-kit/le-button.le-checkbox.le-component.le-popover.le-popup.le-slot.le-string-input.entry.esm.js.map +0 -1
  209. package/dist/le-kit/le-dropdown-base.entry.esm.js.map +0 -1
  210. package/dist/le-kit/le-select.entry.esm.js.map +0 -1
  211. package/dist/le-kit/p-4130c60b.entry.js +0 -2
  212. package/dist/le-kit/p-4130c60b.entry.js.map +0 -1
  213. package/dist/le-kit/p-DaA5gINj.js +0 -2
  214. package/dist/le-kit/p-DzgCnDLJ.js +0 -3
  215. package/dist/le-kit/p-DzgCnDLJ.js.map +0 -1
  216. package/dist/le-kit/p-beb87e61.entry.js +0 -2
  217. package/dist/le-kit/p-cc0797b0.entry.js +0 -2
  218. package/dist/le-kit/p-cc0797b0.entry.js.map +0 -1
  219. package/dist/le-kit/p-d504a369.entry.js +0 -2
  220. package/dist/le-kit/p-d504a369.entry.js.map +0 -1
  221. /package/dist/le-kit/{p-1f55a4a2.entry.js.map → p-13a4dc1d.entry.js.map} +0 -0
  222. /package/dist/le-kit/{p-0bd7803f.entry.js.map → p-1a9e65d0.entry.js.map} +0 -0
  223. /package/dist/le-kit/{p-7b180d58.entry.js.map → p-32cbb683.entry.js.map} +0 -0
  224. /package/dist/le-kit/{p-71c78784.entry.js.map → p-476e1886.entry.js.map} +0 -0
  225. /package/dist/le-kit/{p-beb87e61.entry.js.map → p-67d702f9.entry.js.map} +0 -0
  226. /package/dist/le-kit/{p-33612923.entry.js.map → p-6884e3e8.entry.js.map} +0 -0
  227. /package/dist/le-kit/{p-6ecdad85.entry.js.map → p-704ad5e0.entry.js.map} +0 -0
  228. /package/dist/le-kit/{p-432e8231.entry.js.map → p-88f9aa40.entry.js.map} +0 -0
  229. /package/dist/le-kit/{p-91993261.entry.js.map → p-8dd8a487.entry.js.map} +0 -0
  230. /package/dist/le-kit/{p-6ee06c44.entry.js.map → p-97b7658a.entry.js.map} +0 -0
  231. /package/dist/le-kit/{p-a5d31d40.entry.js.map → p-c0925e92.entry.js.map} +0 -0
  232. /package/dist/le-kit/{p-548d130b.entry.js.map → p-c2494a0d.entry.js.map} +0 -0
  233. /package/dist/le-kit/{p-3a52c4de.entry.js.map → p-ded51018.entry.js.map} +0 -0
  234. /package/dist/le-kit/{p-2c37f174.entry.js.map → p-e3db7974.entry.js.map} +0 -0
  235. /package/dist/le-kit/{p-b66fd9e1.entry.js.map → p-f9b03aec.entry.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"utils-DjPcLPN9.js","sources":["src/utils/utils.ts"],"sourcesContent":["/**\n * Utility functions for le-kit components\n */\n\nimport { getMode } from '../global/app';\n\n/**\n * Generates a unique ID for component instances\n */\nexport function generateId(prefix: string = 'le'): string {\n return `${prefix}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Parses a comma-separated string into an array\n */\nexport function parseCommaSeparated(value: string | undefined): string[] {\n if (!value) return [];\n return value\n .split(',')\n .map(s => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Checks if a slot has content\n */\nexport function slotHasContent(el: HTMLElement, slotName: string = ''): boolean {\n const selector = slotName ? `[slot=\"${slotName}\"]` : ':not([slot])';\n return el.querySelector(selector) !== null;\n}\n\n/**\n * Sets up a MutationObserver to track mode changes on ancestor elements.\n * Returns a cleanup function to disconnect the observer.\n * \n * If the element or any ancestor has an explicit `mode` attribute, that creates\n * a \"mode boundary\" - the mode is determined from that point, not from further up.\n * This allows components like le-popover to force default mode for their children.\n * \n * @param el - The component's host element\n * @param callback - Function to call when mode changes, receives the new mode\n * @returns Cleanup function to disconnect the observer\n * \n * @example\n * ```tsx\n * export class MyComponent {\n * @Element() el: HTMLElement;\n * @State() adminMode: boolean = false;\n * private disconnectModeObserver?: () => void;\n * \n * connectedCallback() {\n * this.disconnectModeObserver = observeModeChanges(this.el, (mode) => {\n * this.adminMode = mode === 'admin';\n * });\n * }\n * \n * disconnectedCallback() {\n * this.disconnectModeObserver?.();\n * }\n * }\n * ```\n */\nexport function observeModeChanges(\n el: HTMLElement,\n callback: (mode: string) => void\n): () => void {\n // Call immediately with current mode\n callback(getMode(el));\n\n // Set up observer for mode attribute changes\n const observer = new MutationObserver(() => {\n callback(getMode(el));\n });\n\n // Observe the element itself (for mode boundary changes)\n observer.observe(el, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n\n // Observe document root\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n\n // Traverse up, crossing shadow boundaries, and observe each element\n let current: Node | null = el;\n while (current) {\n if (current instanceof Element && current.parentElement) {\n current = current.parentElement;\n observer.observe(current, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n // If this element has an explicit mode, it's a boundary\n if ((current as Element).hasAttribute('mode')) {\n break;\n }\n } else {\n // Check if we're in a shadow root\n const root = current.getRootNode();\n if (root instanceof ShadowRoot) {\n // Cross the shadow boundary and observe the host\n current = root.host;\n observer.observe(current, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n // If the host has an explicit mode, it's a boundary\n if ((current as Element).hasAttribute('mode')) {\n break;\n }\n } else {\n break;\n }\n }\n }\n\n // Return cleanup function\n return () => observer.disconnect();\n}\n\n/**\n * Combines multiple class names into a single string, filtering out falsy values.\n * \n * @param classes - arguments of class names, undefined, arrays, objects with boolean values and nested combinations of these\n * @returns Combined class names string\n */\nexport function classnames(...classes: any[]): string {\n const result: string[] = [];\n\n classes.forEach(cls => {\n if (!cls) return;\n\n if (typeof cls === 'string') {\n result.push(cls);\n } else if (Array.isArray(cls)) {\n result.push(classnames(...cls));\n } else if (typeof cls === 'object') {\n Object.entries(cls).forEach(([key, value]) => {\n if (value) {\n result.push(key);\n }\n });\n }\n });\n\n return result.join(' ');\n}\n"],"names":["getMode"],"mappings":"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"}
1
+ {"version":3,"file":"utils-CYOKcOW8.js","sources":["src/utils/utils.ts"],"sourcesContent":["/**\n * Utility functions for le-kit components\n */\n\nimport { getMode } from '../global/app';\n\n/**\n * Generates a unique ID for component instances\n */\nexport function generateId(prefix: string = 'le'): string {\n return `${prefix}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Parses a comma-separated string into an array\n */\nexport function parseCommaSeparated(value: string | undefined): string[] {\n if (!value) return [];\n return value\n .split(',')\n .map(s => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Checks if a slot has content\n */\nexport function slotHasContent(el: HTMLElement, slotName: string = ''): boolean {\n const selector = slotName ? `[slot=\"${slotName}\"]` : ':not([slot])';\n return el.querySelector(selector) !== null;\n}\n\n/**\n * Sets up a MutationObserver to track mode changes on ancestor elements.\n * Returns a cleanup function to disconnect the observer.\n * \n * If the element or any ancestor has an explicit `mode` attribute, that creates\n * a \"mode boundary\" - the mode is determined from that point, not from further up.\n * This allows components like le-popover to force default mode for their children.\n * \n * @param el - The component's host element\n * @param callback - Function to call when mode changes, receives the new mode\n * @returns Cleanup function to disconnect the observer\n * \n * @example\n * ```tsx\n * export class MyComponent {\n * @Element() el: HTMLElement;\n * @State() adminMode: boolean = false;\n * private disconnectModeObserver?: () => void;\n * \n * connectedCallback() {\n * this.disconnectModeObserver = observeModeChanges(this.el, (mode) => {\n * this.adminMode = mode === 'admin';\n * });\n * }\n * \n * disconnectedCallback() {\n * this.disconnectModeObserver?.();\n * }\n * }\n * ```\n */\nexport function observeModeChanges(\n el: HTMLElement,\n callback: (mode: string) => void\n): () => void {\n // Call immediately with current mode\n callback(getMode(el));\n\n // Set up observer for mode attribute changes\n const observer = new MutationObserver(() => {\n callback(getMode(el));\n });\n\n // Observe the element itself (for mode boundary changes)\n observer.observe(el, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n\n // Observe document root\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n\n // Traverse up, crossing shadow boundaries, and observe each element\n let current: Node | null = el;\n while (current) {\n if (current instanceof Element && current.parentElement) {\n current = current.parentElement;\n observer.observe(current, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n // If this element has an explicit mode, it's a boundary\n if ((current as Element).hasAttribute('mode')) {\n break;\n }\n } else {\n // Check if we're in a shadow root\n const root = current.getRootNode();\n if (root instanceof ShadowRoot) {\n // Cross the shadow boundary and observe the host\n current = root.host;\n observer.observe(current, {\n attributes: true,\n attributeFilter: ['mode'],\n });\n // If the host has an explicit mode, it's a boundary\n if ((current as Element).hasAttribute('mode')) {\n break;\n }\n } else {\n break;\n }\n }\n }\n\n // Return cleanup function\n return () => observer.disconnect();\n}\n\n/**\n * Combines multiple class names into a single string, filtering out falsy values.\n * \n * @param classes - arguments of class names, undefined, arrays, objects with boolean values and nested combinations of these\n * @returns Combined class names string\n */\nexport function classnames(...classes: any[]): string {\n const result: string[] = [];\n\n classes.forEach(cls => {\n if (!cls) return;\n\n if (typeof cls === 'string') {\n result.push(cls);\n } else if (Array.isArray(cls)) {\n result.push(classnames(...cls));\n } else if (typeof cls === 'object') {\n Object.entries(cls).forEach(([key, value]) => {\n if (value) {\n result.push(key);\n }\n });\n }\n });\n\n return result.join(' ');\n}\n"],"names":["getMode"],"mappings":"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"}
@@ -5,13 +5,18 @@
5
5
  "components/le-button/le-button.js",
6
6
  "components/le-card/le-card.js",
7
7
  "components/le-checkbox/le-checkbox.js",
8
+ "components/le-collapse/le-collapse.js",
8
9
  "components/le-combobox/le-combobox.js",
9
10
  "components/le-component/le-component.js",
11
+ "components/le-current-heading/le-current-heading.js",
10
12
  "components/le-dropdown-base/le-dropdown-base.js",
13
+ "components/le-header/le-header.js",
14
+ "components/le-header-placeholder/le-header-placeholder.js",
11
15
  "components/le-multiselect/le-multiselect.js",
12
16
  "components/le-number-input/le-number-input.js",
13
17
  "components/le-popover/le-popover.js",
14
18
  "components/le-round-progress/le-round-progress.js",
19
+ "components/le-scroll-progress/le-scroll-progress.js",
15
20
  "components/le-segmented-control/le-segmented-control.js",
16
21
  "components/le-select/le-select.js",
17
22
  "components/le-slot/le-slot.js",
@@ -0,0 +1,31 @@
1
+ :host {
2
+ --le-collapse-duration: var(--le-transition-normal);
3
+
4
+ display: grid;
5
+ grid-template-rows: 1fr;
6
+ opacity: 1;
7
+ transition:
8
+ grid-template-rows var(--le-collapse-duration),
9
+ opacity var(--le-collapse-duration);
10
+ }
11
+
12
+ :host([data-open="false"]),
13
+ :host([open="false"]) {
14
+ grid-template-rows: 0fr;
15
+ opacity: 0;
16
+ }
17
+ :host([no-fading][data-open="false"]),
18
+ :host([no-fading][open="false"]) {
19
+ opacity: 1;
20
+ }
21
+
22
+ .region {
23
+ display: flex;
24
+ flex-direction: column;
25
+ justify-content: flex-end;
26
+ overflow: hidden;
27
+ }
28
+
29
+ :host([scroll-down]) .region {
30
+ justify-content: flex-start;
31
+ }
@@ -0,0 +1,188 @@
1
+ import { h, Host } from "@stencil/core";
2
+ /**
3
+ * Animated show/hide wrapper.
4
+ *
5
+ * Supports height collapse (auto->0) and/or fading.
6
+ * Can optionally listen to the nearest `le-header` shrink events.
7
+ *
8
+ * @slot - Content to animate
9
+ *
10
+ * @cssprop --le-collapse-duration - Transition duration
11
+ *
12
+ * @csspart region - Collapsible region
13
+ * @csspart content - Inner content
14
+ *
15
+ * @cmsEditable true
16
+ * @cmsCategory Layout
17
+ */
18
+ export class LeCollapse {
19
+ el;
20
+ /** Whether the content should be shown. */
21
+ open = true;
22
+ /** Whether the content should scroll down from the top when open. */
23
+ scrollDown = false;
24
+ /** Stop fading the content when collapsing/expanding. */
25
+ noFading = false;
26
+ /** If true, collapse/expand based on the nearest header shrink event. */
27
+ collapseOnHeaderShrink = false;
28
+ /**
29
+ * Handles `leHeaderShrinkChange` events from the `le-header`.
30
+ * In case multiple headers are present, only the nearest one in the DOM tree is used.
31
+ */
32
+ handleHeaderShrink(ev) {
33
+ const e = ev;
34
+ this.headerShrunk = !!e.detail?.shrunk;
35
+ }
36
+ headerShrunk = false;
37
+ componentWillLoad() {
38
+ // Stencil boolean props default to `false` when the attribute is missing.
39
+ // For this component, the desired default is open=true.
40
+ if (!this.el.hasAttribute('open')) {
41
+ this.open = true;
42
+ }
43
+ }
44
+ componentDidLoad() {
45
+ this.applyOpenState();
46
+ }
47
+ onOpenChange() {
48
+ this.applyOpenState();
49
+ }
50
+ onDrivenStateChange() {
51
+ this.applyOpenState();
52
+ }
53
+ shouldBeOpen() {
54
+ if (!this.open)
55
+ return false;
56
+ if (this.collapseOnHeaderShrink && this.headerShrunk)
57
+ return false;
58
+ return true;
59
+ }
60
+ applyOpenState() {
61
+ const nextOpen = this.shouldBeOpen();
62
+ this.el.toggleAttribute('data-open', nextOpen);
63
+ }
64
+ render() {
65
+ return (h(Host, { key: '30fe288583bae1645ce00714de95c40ed92b7af0', "data-open": this.shouldBeOpen() ? 'true' : 'false' }, h("le-component", { key: '5fdc1e83caaff73fedb61d7286fc56f03fa8127a', component: "le-collapse" }, h("div", { key: '185df372a5039be23abf42ff262ef2d3eaa1602f', class: "region", part: "region" }, h("slot", { key: '1790f5457264342d71aecb94a67ce4ee11149af2' })))));
66
+ }
67
+ static get is() { return "le-collapse"; }
68
+ static get encapsulation() { return "shadow"; }
69
+ static get originalStyleUrls() {
70
+ return {
71
+ "$": ["le-collapse.css"]
72
+ };
73
+ }
74
+ static get styleUrls() {
75
+ return {
76
+ "$": ["le-collapse.css"]
77
+ };
78
+ }
79
+ static get properties() {
80
+ return {
81
+ "open": {
82
+ "type": "boolean",
83
+ "mutable": true,
84
+ "complexType": {
85
+ "original": "boolean",
86
+ "resolved": "boolean",
87
+ "references": {}
88
+ },
89
+ "required": false,
90
+ "optional": false,
91
+ "docs": {
92
+ "tags": [],
93
+ "text": "Whether the content should be shown."
94
+ },
95
+ "getter": false,
96
+ "setter": false,
97
+ "reflect": true,
98
+ "attribute": "open",
99
+ "defaultValue": "true"
100
+ },
101
+ "scrollDown": {
102
+ "type": "boolean",
103
+ "mutable": false,
104
+ "complexType": {
105
+ "original": "boolean",
106
+ "resolved": "boolean",
107
+ "references": {}
108
+ },
109
+ "required": false,
110
+ "optional": false,
111
+ "docs": {
112
+ "tags": [],
113
+ "text": "Whether the content should scroll down from the top when open."
114
+ },
115
+ "getter": false,
116
+ "setter": false,
117
+ "reflect": true,
118
+ "attribute": "scroll-down",
119
+ "defaultValue": "false"
120
+ },
121
+ "noFading": {
122
+ "type": "boolean",
123
+ "mutable": false,
124
+ "complexType": {
125
+ "original": "boolean",
126
+ "resolved": "boolean",
127
+ "references": {}
128
+ },
129
+ "required": false,
130
+ "optional": false,
131
+ "docs": {
132
+ "tags": [],
133
+ "text": "Stop fading the content when collapsing/expanding."
134
+ },
135
+ "getter": false,
136
+ "setter": false,
137
+ "reflect": true,
138
+ "attribute": "no-fading",
139
+ "defaultValue": "false"
140
+ },
141
+ "collapseOnHeaderShrink": {
142
+ "type": "boolean",
143
+ "mutable": false,
144
+ "complexType": {
145
+ "original": "boolean",
146
+ "resolved": "boolean",
147
+ "references": {}
148
+ },
149
+ "required": false,
150
+ "optional": false,
151
+ "docs": {
152
+ "tags": [],
153
+ "text": "If true, collapse/expand based on the nearest header shrink event."
154
+ },
155
+ "getter": false,
156
+ "setter": false,
157
+ "reflect": true,
158
+ "attribute": "collapse-on-header-shrink",
159
+ "defaultValue": "false"
160
+ }
161
+ };
162
+ }
163
+ static get states() {
164
+ return {
165
+ "headerShrunk": {}
166
+ };
167
+ }
168
+ static get elementRef() { return "el"; }
169
+ static get watchers() {
170
+ return [{
171
+ "propName": "open",
172
+ "methodName": "onOpenChange"
173
+ }, {
174
+ "propName": "headerShrunk",
175
+ "methodName": "onDrivenStateChange"
176
+ }];
177
+ }
178
+ static get listeners() {
179
+ return [{
180
+ "name": "leHeaderShrinkChange",
181
+ "method": "handleHeaderShrink",
182
+ "target": "window",
183
+ "capture": false,
184
+ "passive": false
185
+ }];
186
+ }
187
+ }
188
+ //# sourceMappingURL=le-collapse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"le-collapse.js","sourceRoot":"","sources":["../../../src/components/le-collapse/le-collapse.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAIxF;;;;;;;;;;;;;;;GAeG;AAMH,MAAM,OAAO,UAAU;IACV,EAAE,CAAc;IAE3B,2CAA2C;IACH,IAAI,GAAY,IAAI,CAAC;IAE7D,qEAAqE;IAClB,UAAU,GAAY,KAAK,CAAC;IAE/E,yDAAyD;IACR,QAAQ,GAAY,KAAK,CAAC;IAE3E,yEAAyE;IACR,sBAAsB,GACrF,KAAK,CAAC;IAER;;;OAGG;IAEH,kBAAkB,CAAC,EAAS;QAC1B,MAAM,CAAC,GAAG,EAAsC,CAAC;QACjD,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC;IACzC,CAAC;IAEgB,YAAY,GAAY,KAAK,CAAC;IAE/C,iBAAiB;QACf,0EAA0E;QAC1E,wDAAwD;QACxD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAGS,YAAY;QACpB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAGS,mBAAmB;QAC3B,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QAC7B,IAAI,IAAI,CAAC,sBAAsB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,KAAK,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,cAAc;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,MAAM;QACJ,OAAO,CACL,EAAC,IAAI,kEAAY,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;YACrD,qEAAc,SAAS,EAAC,aAAa;gBACnC,4DAAK,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,QAAQ;oBAC/B,8DAAa,CACT,CACO,CACV,CACR,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Element, h, Host, Listen, Prop, State, Watch } from '@stencil/core';\n\nexport type LeCollapseAnimation = 'fade' | 'collapse' | 'fade-collapse';\n\n/**\n * Animated show/hide wrapper.\n *\n * Supports height collapse (auto->0) and/or fading.\n * Can optionally listen to the nearest `le-header` shrink events.\n *\n * @slot - Content to animate\n *\n * @cssprop --le-collapse-duration - Transition duration\n *\n * @csspart region - Collapsible region\n * @csspart content - Inner content\n *\n * @cmsEditable true\n * @cmsCategory Layout\n */\n@Component({\n tag: 'le-collapse',\n styleUrl: 'le-collapse.css',\n shadow: true,\n})\nexport class LeCollapse {\n @Element() el: HTMLElement;\n\n /** Whether the content should be shown. */\n @Prop({ mutable: true, reflect: true }) open: boolean = true;\n\n /** Whether the content should scroll down from the top when open. */\n @Prop({ attribute: 'scroll-down', reflect: true }) scrollDown: boolean = false;\n\n /** Stop fading the content when collapsing/expanding. */\n @Prop({ attribute: 'no-fading', reflect: true }) noFading: boolean = false;\n\n /** If true, collapse/expand based on the nearest header shrink event. */\n @Prop({ attribute: 'collapse-on-header-shrink', reflect: true }) collapseOnHeaderShrink: boolean =\n false;\n\n /**\n * Handles `leHeaderShrinkChange` events from the `le-header`.\n * In case multiple headers are present, only the nearest one in the DOM tree is used.\n */\n @Listen('leHeaderShrinkChange', { target: 'window' })\n handleHeaderShrink(ev: Event) {\n const e = ev as CustomEvent<{ shrunk: boolean }>;\n this.headerShrunk = !!e.detail?.shrunk;\n }\n\n @State() private headerShrunk: boolean = false;\n\n componentWillLoad() {\n // Stencil boolean props default to `false` when the attribute is missing.\n // For this component, the desired default is open=true.\n if (!this.el.hasAttribute('open')) {\n this.open = true;\n }\n }\n\n componentDidLoad() {\n this.applyOpenState();\n }\n\n @Watch('open')\n protected onOpenChange() {\n this.applyOpenState();\n }\n\n @Watch('headerShrunk')\n protected onDrivenStateChange() {\n this.applyOpenState();\n }\n\n private shouldBeOpen() {\n if (!this.open) return false;\n if (this.collapseOnHeaderShrink && this.headerShrunk) return false;\n return true;\n }\n\n private applyOpenState() {\n const nextOpen = this.shouldBeOpen();\n this.el.toggleAttribute('data-open', nextOpen);\n }\n\n render() {\n return (\n <Host data-open={this.shouldBeOpen() ? 'true' : 'false'}>\n <le-component component=\"le-collapse\">\n <div class=\"region\" part=\"region\">\n <slot></slot>\n </div>\n </le-component>\n </Host>\n );\n }\n}\n"]}
@@ -238,7 +238,7 @@ export class LeCombobox {
238
238
  }
239
239
  render() {
240
240
  const hasValue = this.inputValue.length > 0;
241
- return (h("le-component", { key: '387d52e3054515ecb8b46116deae909fcdb75969', component: "le-combobox" }, h("le-dropdown-base", { key: '822f479f2a831a7e817a38318c021bf2f52b3ed7', ref: el => (this.dropdownEl = el), options: this.parsedOptions, value: this.value, disabled: this.disabled, filterFn: this.filterOption, filterQuery: this.inputValue, emptyText: this.emptyText, fullWidth: this.fullWidth, closeOnClickOutside: false, onLeOptionSelect: this.handleOptionSelect, onLeDropdownOpen: this.handleDropdownOpen, onLeDropdownClose: this.handleDropdownClose }, h("div", { key: '7c57078e2ee0dd371d44f4fafdb8cf5e5914dfee', slot: "trigger", class: { 'combobox-trigger': true, 'is-open': this.open } }, h("le-string-input", { key: 'fbdc0d1c4d82a4fb6021a51a3b48752be37ade2c', mode: "default", hideDescription: true, inputRef: el => (this.inputEl = el), type: "text", class: "combobox-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, "aria-haspopup": "listbox", "aria-expanded": this.open ? 'true' : 'false', "aria-autocomplete": "list", onInput: this.handleInputChange, onFocus: this.handleInputFocus, onKeyDown: this.handleInputKeyDown }), hasValue && !this.disabled && (h("button", { key: 'a17932b0f41065d5550c343851664bc3967a8341', type: "button", class: "combobox-clear", onClick: this.handleClear, "aria-label": "Clear", tabIndex: -1 }, h("svg", { key: '8ed3c6c92c76152f0898f4f87e69efffacee7aad', viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: '985476db5f5f36562069513ffd4d873fb83c1f71', d: "M4 4l8 8M12 4l-8 8" })))), h("span", { key: '72663ad4b72f476e35a1024e66f495a343c22006', class: "combobox-arrow" }, h("svg", { key: '7a5ae4711763398b9196bd5ab86043de8579debf', viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: '9722bd7f24ede8f9c3ee16e0e3ce19234ef38a26', d: "M4 6l4 4 4-4" }))))), this.name && h("input", { key: '5df357f53be8683145e4fbc3e5434807505fd98f', type: "hidden", name: this.name, value: this.value?.toString() ?? '' })));
241
+ return (h("le-component", { key: '465108f53d7f7f4952288894d9e8fe7963d37275', component: "le-combobox" }, h("le-dropdown-base", { key: '202960374cb445e5b45856dd50f973ebfbdc9b8d', ref: el => (this.dropdownEl = el), options: this.parsedOptions, value: this.value, disabled: this.disabled, filterFn: this.filterOption, filterQuery: this.inputValue, emptyText: this.emptyText, fullWidth: this.fullWidth, closeOnClickOutside: false, onLeOptionSelect: this.handleOptionSelect, onLeDropdownOpen: this.handleDropdownOpen, onLeDropdownClose: this.handleDropdownClose }, h("div", { key: 'a45f5c63e4b4f854b076a59b89b2002ae4ad7647', slot: "trigger", class: { 'combobox-trigger': true, 'is-open': this.open } }, h("le-string-input", { key: '1b4ba18526eb55434dec28d6a033bdb8a2db6d79', mode: "default", hideDescription: true, inputRef: el => (this.inputEl = el), type: "text", class: "combobox-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, "aria-haspopup": "listbox", "aria-expanded": this.open ? 'true' : 'false', "aria-autocomplete": "list", onInput: this.handleInputChange, onFocus: this.handleInputFocus, onKeyDown: this.handleInputKeyDown }), hasValue && !this.disabled && (h("button", { key: '950b1a1ba5b8060b373c8fb0f25f64d29b38d5b9', type: "button", class: "combobox-clear", onClick: this.handleClear, "aria-label": "Clear", tabIndex: -1 }, h("svg", { key: '43c975d5797cf669c298d96e4fcd85d85fcf5780', viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: 'b3ab58b014abac2cc509447b940d3f95d713f2c2', d: "M4 4l8 8M12 4l-8 8" })))), h("span", { key: '32723ec3ebcd615c8fdd3f8e29bc7e418efdfd17', class: "combobox-arrow" }, h("svg", { key: '9cb0e39189b7cffb6723185a7800d93c367e8557', viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: '80f4010bce48ab71a31b9681c18c9d2f6041b763', d: "M4 6l4 4 4-4" }))))), this.name && h("input", { key: 'b1ae25e4537e3fed0d3a9f43ececb85f39e8c57a', type: "hidden", name: this.name, value: this.value?.toString() ?? '' })));
242
242
  }
243
243
  static get is() { return "le-combobox"; }
244
244
  static get encapsulation() { return "shadow"; }
@@ -240,7 +240,7 @@ export class LeComponent {
240
240
  const enumMatch = type.match(/^'[^']+'/);
241
241
  if (enumMatch) {
242
242
  const options = type.split('|').map(opt => opt.trim().replace(/'/g, ''));
243
- return (h("div", { class: "property-field" }, h("label", { htmlFor: `prop-${attr.name}` }, attr.name, attr.description && h("span", { class: "property-hint" }, attr.description)), h("select", { id: `prop-${attr.name}`, onChange: e => this.handlePropertyChange(attr.name, e.target.value, type) }, options.map(opt => (h("option", { value: opt, selected: value === opt || (!value && attr.default?.replace(/'/g, '') === opt) }, opt))))));
243
+ return (h("div", { class: "property-field" }, h("label", { htmlFor: `prop-${attr.name}` }, attr.name, attr.description && h("span", { class: "property-hint" }, attr.description)), h("le-select", { options: [...options.map(opt => ({ label: opt, value: opt }))], "full-width": true, value: value ?? attr.default?.replace(/'/g, ''), placeholder: attr.default?.replace(/'/g, ''), onLeChange: (e) => this.handlePropertyChange(attr.name, e.detail.value, type) })));
244
244
  }
245
245
  // Boolean type
246
246
  if (type === 'boolean') {
@@ -1 +1 @@
1
- {"version":3,"file":"le-component.js","sourceRoot":"","sources":["../../../src/components/le-component/le-component.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Host, Element, getAssetPath } from '@stencil/core';\nimport { classnames, observeModeChanges } from '../../utils/utils';\nimport { getLeKitConfig } from '../../global/app';\nimport { leConfirm } from '../le-popup/le-popup.api';\n\n/**\n * Component wrapper for admin mode editing.\n *\n * This component is used internally by other components to provide admin-mode\n * editing capabilities. It wraps the component's rendered output and shows\n * a settings popover for editing properties.\n *\n * In default mode, it acts as a simple passthrough (display: contents).\n * In admin mode, it shows a border, component name header, and settings popover.\n *\n * The host element is found automatically by traversing up through the shadow DOM.\n *\n * Usage inside a component's render method:\n * ```tsx\n * render() {\n * return (\n * <le-component component=\"le-card\">\n * <Host>...</Host>\n * </le-component>\n * );\n * }\n * ```\n *\n * @slot - The component's rendered content\n *\n * @cmsInternal true\n * @cmsCategory System\n */\n@Component({\n tag: 'le-component',\n styleUrl: 'le-component.css',\n shadow: true,\n assetsDirs: ['assets'],\n})\nexport class LeComponent {\n @Element() el: HTMLElement;\n\n /**\n * The tag name of the component (e.g., 'le-card').\n * Used to look up property metadata and display the component name.\n */\n @Prop() component!: string;\n\n /**\n * Optional display name for the component.\n * If not provided, the tag name will be formatted as the display name.\n */\n @Prop() displayName?: string;\n\n /**\n * Classes to apply to the host element.\n * Allows parent components to pass their styling classes.\n */\n @Prop() hostClass?: string;\n\n /**\n * Inline styles to apply to the host element.\n * Allows parent components to pass dynamic styles (e.g., flex properties).\n */\n @Prop() hostStyle?: { [key: string]: string };\n\n /**\n * Reference to the host element (found automatically from parent)\n */\n private hostElement?: HTMLElement;\n\n /**\n * Internal state to track admin mode\n */\n @State() private adminMode: boolean = false;\n\n /**\n * Component metadata loaded from Custom Elements Manifest\n */\n @State() private componentMeta: ComponentMetadata | null = null;\n\n /**\n * Current property values of the host component\n */\n @State() private propertyValues: Record<string, any> = {};\n\n private disconnectModeObserver?: () => void;\n\n connectedCallback() {\n // Find the host element - le-component is rendered inside the component's shadow DOM,\n // so we need to find the shadow root's host element\n this.findHostElement();\n\n this.disconnectModeObserver = observeModeChanges(this.el, mode => {\n this.adminMode = mode === 'admin';\n // Load metadata and refresh property values only when entering admin mode\n if (this.adminMode) {\n if (!this.componentMeta) {\n this.loadComponentMetadata();\n } else {\n this.readPropertyValues();\n }\n }\n });\n }\n\n /**\n * Find the host element by traversing up through shadow DOM\n */\n private findHostElement() {\n // Get the shadow root that contains this le-component\n const rootNode = this.el.getRootNode();\n if (rootNode instanceof ShadowRoot) {\n // The host of this shadow root is our target component (e.g., le-card)\n this.hostElement = rootNode.host as HTMLElement;\n }\n }\n\n componentDidLoad() {\n // Read initial property values from the host element\n this.readPropertyValues();\n }\n\n disconnectedCallback() {\n this.disconnectModeObserver?.();\n }\n\n /**\n * Formats a tag name into a display name\n * e.g., 'le-card' -> 'Card'\n */\n private formatDisplayName(tagName: string): string {\n return tagName\n .replace(/^le-/, '') // Remove 'le-' prefix\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n /**\n * Load component metadata from the Custom Elements Manifest\n */\n private async loadComponentMetadata() {\n try {\n // Fetch the manifest from configured URL\n const { manifestFile } = getLeKitConfig();\n const manifestFileResolved = getAssetPath(`./assets/${manifestFile}`);\n const response = await fetch(manifestFileResolved);\n const manifest = await response.json();\n\n // Find the component definition\n for (const module of manifest.modules) {\n for (const declaration of module.declarations || []) {\n if (declaration.tagName === this.component) {\n const attributes = (declaration.attributes || []).filter(\n (attr: AttributeMetadata) => !this.isInternalAttribute(attr.name),\n );\n this.componentMeta = {\n tagName: declaration.tagName,\n description: declaration.description,\n attributes,\n };\n // console.log(`[le-component] Loaded metadata for ${this.component}:`, this.componentMeta);\n // Read property values after metadata is loaded\n this.readPropertyValues();\n return;\n }\n }\n }\n // console.warn(`[le-component] No metadata found for component: ${this.component}`);\n } catch (error) {\n // console.warn(`[le-component] Failed to load metadata for component: ${this.component}`, error);\n }\n }\n\n /**\n * Check if an attribute is internal (should not be shown in editor)\n */\n private isInternalAttribute(name: string): boolean {\n const internalAttrs = ['mode', 'theme', 'class', 'style', 'id', 'slot'];\n return internalAttrs.includes(name);\n }\n\n /**\n * Read current property values from the host element\n */\n private readPropertyValues() {\n if (!this.hostElement || !this.componentMeta) return;\n\n const values: Record<string, any> = {};\n for (const attr of this.componentMeta.attributes) {\n const value = this.hostElement.getAttribute(attr.name);\n values[attr.name] = this.parseAttributeValue(value, attr.type?.text);\n }\n this.propertyValues = values;\n }\n\n /**\n * Parse an attribute value based on its type\n */\n private parseAttributeValue(value: string | null, type?: string): any {\n if (value === null) return undefined;\n\n if (type === 'boolean') {\n return value !== null && value !== 'false';\n }\n if (type === 'number') {\n return parseFloat(value);\n }\n return value;\n }\n\n /**\n * Handle property value changes from the editor\n */\n private handlePropertyChange(attrName: string, value: any, type?: string) {\n if (!this.hostElement) return;\n\n // Update the host element's attribute\n if (type === 'boolean') {\n if (value) {\n this.hostElement.setAttribute(attrName, '');\n } else {\n this.hostElement.removeAttribute(attrName);\n }\n } else if (value === undefined || value === '') {\n this.hostElement.removeAttribute(attrName);\n } else {\n this.hostElement.setAttribute(attrName, String(value));\n }\n\n // Update local state\n this.propertyValues = { ...this.propertyValues, [attrName]: value };\n\n // update the host element the way the parent element mutation observer would catch it?\n }\n\n /**\n * Delete this component from the DOM\n */\n private deleteComponent() {\n if (!this.hostElement) return;\n\n // Confirm deletion\n const name = this.displayName || this.formatDisplayName(this.component);\n if (!leConfirm(`Delete this ${name}?`)) return;\n\n // Remove the host element from its parent\n const parent = this.hostElement.parentElement;\n if (parent) {\n this.hostElement.remove();\n }\n }\n\n /**\n * Render the property editor form\n */\n private renderPropertyEditor() {\n const hasProperties = this.componentMeta && this.componentMeta.attributes.length > 0;\n\n return (\n <div class=\"property-editor-container\">\n {hasProperties ? (\n <form class=\"property-editor\" onSubmit={e => e.preventDefault()}>\n {this.componentMeta!.attributes.map(attr => this.renderPropertyField(attr))}\n </form>\n ) : (\n <p class=\"no-properties\">No editable properties</p>\n )}\n <div class=\"property-editor-actions\">\n <le-button\n type=\"button\"\n variant=\"outlined\"\n color=\"danger\"\n full-width\n onClick={() => this.deleteComponent()}\n >\n <span slot=\"icon-start\">🗑️</span>\n <span>Delete Component</span>\n </le-button>\n </div>\n </div>\n );\n }\n\n /**\n * Render a single property field based on its type\n */\n private renderPropertyField(attr: AttributeMetadata) {\n const value = this.propertyValues[attr.name];\n const type = attr.type?.text || 'string';\n\n // Check if type is a union of string literals (e.g., \"'default' | 'outlined' | 'elevated'\")\n const enumMatch = type.match(/^'[^']+'/);\n if (enumMatch) {\n const options = type.split('|').map(opt => opt.trim().replace(/'/g, ''));\n return (\n <div class=\"property-field\">\n <label htmlFor={`prop-${attr.name}`}>\n {attr.name}\n {attr.description && <span class=\"property-hint\">{attr.description}</span>}\n </label>\n {/* <le-select\n options={[...options.map(opt => ({ label: opt, value: opt }))]}\n full-width\n value={value ?? attr.default?.replace(/'/g, '')}\n placeholder={attr.default?.replace(/'/g, '')}\n onLeChange={(e: CustomEvent<LeOptionSelectDetail>) =>\n this.handlePropertyChange(attr.name, e.detail.value, type)\n }\n ></le-select> */}\n <select\n id={`prop-${attr.name}`}\n onChange={e =>\n this.handlePropertyChange(attr.name, (e.target as HTMLSelectElement).value, type)\n }\n >\n {options.map(opt => (\n <option\n value={opt}\n selected={value === opt || (!value && attr.default?.replace(/'/g, '') === opt)}\n >\n {opt}\n </option>\n ))}\n </select>\n </div>\n );\n }\n\n // Boolean type\n if (type === 'boolean') {\n return (\n <div class=\"property-field property-field--checkbox\">\n <le-checkbox\n name={`prop-${attr.name}`}\n checked={value === true || value === ''}\n onChange={e =>\n this.handlePropertyChange(attr.name, (e.target as HTMLInputElement).checked, type)\n }\n >\n {attr.name}\n {attr.description && <div slot=\"description\">{attr.description}</div>}\n </le-checkbox>\n </div>\n );\n }\n\n // Number type\n if (type === 'number') {\n return (\n <div class=\"property-field\">\n <label htmlFor={`prop-${attr.name}`}>\n {attr.name}\n {attr.description && <span class=\"property-hint\">{attr.description}</span>}\n </label>\n <input\n type=\"number\"\n id={`prop-${attr.name}`}\n value={value ?? ''}\n placeholder={attr.default}\n onChange={e =>\n this.handlePropertyChange(attr.name, (e.target as HTMLInputElement).value, type)\n }\n />\n </div>\n );\n }\n\n // Default: string/text input\n return (\n <div class=\"property-field\">\n <le-string-input\n name={`prop-${attr.name}`}\n label={attr.name}\n value={value ?? ''}\n placeholder={attr.default?.replace(/'/g, '')}\n onChange={(e: any) => this.handlePropertyChange(attr.name, e.detail.value, type)}\n >\n <span slot=\"description\">{attr.description}</span>\n </le-string-input>\n </div>\n );\n }\n\n render() {\n const name = this.displayName || this.formatDisplayName(this.component);\n\n // In default mode, just pass through content with host classes\n if (!this.adminMode) {\n return (\n <Host class={classnames(this.component, this.hostClass)} style={this.hostStyle}>\n <slot></slot>\n </Host>\n );\n }\n\n // In admin mode, show wrapper with header and settings\n return (\n <Host class={classnames(this.component, this.hostClass, 'admin-mode')} style={this.hostStyle}>\n <div class=\"le-component-wrapper\">\n <div class=\"le-component-header\">\n <span class=\"le-component-name\">{name}</span>\n <le-popover\n popoverTitle={`${name} Settings`}\n position=\"right\"\n align=\"start\"\n min-width=\"300px\"\n mode=\"default\"\n >\n <le-button\n type=\"button\"\n class=\"le-component-button\"\n slot=\"trigger\"\n variant=\"clear\"\n size=\"small\"\n aria-label=\"Edit component properties\"\n icon-only\n >\n <span class=\"le-component-trigger\" slot=\"icon-only\">\n ⚙\n </span>\n </le-button>\n {this.renderPropertyEditor()}\n </le-popover>\n </div>\n <div class=\"le-component-content\">\n <slot></slot>\n </div>\n </div>\n </Host>\n );\n }\n}\n\n/**\n * Type definitions for component metadata\n */\ninterface ComponentMetadata {\n tagName: string;\n description?: string;\n attributes: AttributeMetadata[];\n}\n\ninterface AttributeMetadata {\n name: string;\n fieldName?: string;\n description?: string;\n default?: string;\n type?: {\n text: string;\n };\n}\n"]}
1
+ {"version":3,"file":"le-component.js","sourceRoot":"","sources":["../../../src/components/le-component/le-component.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, State, h, Host, Element, getAssetPath } from '@stencil/core';\nimport { classnames, observeModeChanges } from '../../utils/utils';\nimport { getLeKitConfig } from '../../global/app';\nimport { leConfirm } from '../le-popup/le-popup.api';\nimport { LeOptionSelectDetail } from '../..';\n\n/**\n * Component wrapper for admin mode editing.\n *\n * This component is used internally by other components to provide admin-mode\n * editing capabilities. It wraps the component's rendered output and shows\n * a settings popover for editing properties.\n *\n * In default mode, it acts as a simple passthrough (display: contents).\n * In admin mode, it shows a border, component name header, and settings popover.\n *\n * The host element is found automatically by traversing up through the shadow DOM.\n *\n * Usage inside a component's render method:\n * ```tsx\n * render() {\n * return (\n * <le-component component=\"le-card\">\n * <Host>...</Host>\n * </le-component>\n * );\n * }\n * ```\n *\n * @slot - The component's rendered content\n *\n * @cmsInternal true\n * @cmsCategory System\n */\n@Component({\n tag: 'le-component',\n styleUrl: 'le-component.css',\n shadow: true,\n assetsDirs: ['assets'],\n})\nexport class LeComponent {\n @Element() el: HTMLElement;\n\n /**\n * The tag name of the component (e.g., 'le-card').\n * Used to look up property metadata and display the component name.\n */\n @Prop() component!: string;\n\n /**\n * Optional display name for the component.\n * If not provided, the tag name will be formatted as the display name.\n */\n @Prop() displayName?: string;\n\n /**\n * Classes to apply to the host element.\n * Allows parent components to pass their styling classes.\n */\n @Prop() hostClass?: string;\n\n /**\n * Inline styles to apply to the host element.\n * Allows parent components to pass dynamic styles (e.g., flex properties).\n */\n @Prop() hostStyle?: { [key: string]: string };\n\n /**\n * Reference to the host element (found automatically from parent)\n */\n private hostElement?: HTMLElement;\n\n /**\n * Internal state to track admin mode\n */\n @State() private adminMode: boolean = false;\n\n /**\n * Component metadata loaded from Custom Elements Manifest\n */\n @State() private componentMeta: ComponentMetadata | null = null;\n\n /**\n * Current property values of the host component\n */\n @State() private propertyValues: Record<string, any> = {};\n\n private disconnectModeObserver?: () => void;\n\n connectedCallback() {\n // Find the host element - le-component is rendered inside the component's shadow DOM,\n // so we need to find the shadow root's host element\n this.findHostElement();\n\n this.disconnectModeObserver = observeModeChanges(this.el, mode => {\n this.adminMode = mode === 'admin';\n // Load metadata and refresh property values only when entering admin mode\n if (this.adminMode) {\n if (!this.componentMeta) {\n this.loadComponentMetadata();\n } else {\n this.readPropertyValues();\n }\n }\n });\n }\n\n /**\n * Find the host element by traversing up through shadow DOM\n */\n private findHostElement() {\n // Get the shadow root that contains this le-component\n const rootNode = this.el.getRootNode();\n if (rootNode instanceof ShadowRoot) {\n // The host of this shadow root is our target component (e.g., le-card)\n this.hostElement = rootNode.host as HTMLElement;\n }\n }\n\n componentDidLoad() {\n // Read initial property values from the host element\n this.readPropertyValues();\n }\n\n disconnectedCallback() {\n this.disconnectModeObserver?.();\n }\n\n /**\n * Formats a tag name into a display name\n * e.g., 'le-card' -> 'Card'\n */\n private formatDisplayName(tagName: string): string {\n return tagName\n .replace(/^le-/, '') // Remove 'le-' prefix\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n /**\n * Load component metadata from the Custom Elements Manifest\n */\n private async loadComponentMetadata() {\n try {\n // Fetch the manifest from configured URL\n const { manifestFile } = getLeKitConfig();\n const manifestFileResolved = getAssetPath(`./assets/${manifestFile}`);\n const response = await fetch(manifestFileResolved);\n const manifest = await response.json();\n\n // Find the component definition\n for (const module of manifest.modules) {\n for (const declaration of module.declarations || []) {\n if (declaration.tagName === this.component) {\n const attributes = (declaration.attributes || []).filter(\n (attr: AttributeMetadata) => !this.isInternalAttribute(attr.name),\n );\n this.componentMeta = {\n tagName: declaration.tagName,\n description: declaration.description,\n attributes,\n };\n // console.log(`[le-component] Loaded metadata for ${this.component}:`, this.componentMeta);\n // Read property values after metadata is loaded\n this.readPropertyValues();\n return;\n }\n }\n }\n // console.warn(`[le-component] No metadata found for component: ${this.component}`);\n } catch (error) {\n // console.warn(`[le-component] Failed to load metadata for component: ${this.component}`, error);\n }\n }\n\n /**\n * Check if an attribute is internal (should not be shown in editor)\n */\n private isInternalAttribute(name: string): boolean {\n const internalAttrs = ['mode', 'theme', 'class', 'style', 'id', 'slot'];\n return internalAttrs.includes(name);\n }\n\n /**\n * Read current property values from the host element\n */\n private readPropertyValues() {\n if (!this.hostElement || !this.componentMeta) return;\n\n const values: Record<string, any> = {};\n for (const attr of this.componentMeta.attributes) {\n const value = this.hostElement.getAttribute(attr.name);\n values[attr.name] = this.parseAttributeValue(value, attr.type?.text);\n }\n this.propertyValues = values;\n }\n\n /**\n * Parse an attribute value based on its type\n */\n private parseAttributeValue(value: string | null, type?: string): any {\n if (value === null) return undefined;\n\n if (type === 'boolean') {\n return value !== null && value !== 'false';\n }\n if (type === 'number') {\n return parseFloat(value);\n }\n return value;\n }\n\n /**\n * Handle property value changes from the editor\n */\n private handlePropertyChange(attrName: string, value: any, type?: string) {\n if (!this.hostElement) return;\n\n // Update the host element's attribute\n if (type === 'boolean') {\n if (value) {\n this.hostElement.setAttribute(attrName, '');\n } else {\n this.hostElement.removeAttribute(attrName);\n }\n } else if (value === undefined || value === '') {\n this.hostElement.removeAttribute(attrName);\n } else {\n this.hostElement.setAttribute(attrName, String(value));\n }\n\n // Update local state\n this.propertyValues = { ...this.propertyValues, [attrName]: value };\n\n // update the host element the way the parent element mutation observer would catch it?\n }\n\n /**\n * Delete this component from the DOM\n */\n private deleteComponent() {\n if (!this.hostElement) return;\n\n // Confirm deletion\n const name = this.displayName || this.formatDisplayName(this.component);\n if (!leConfirm(`Delete this ${name}?`)) return;\n\n // Remove the host element from its parent\n const parent = this.hostElement.parentElement;\n if (parent) {\n this.hostElement.remove();\n }\n }\n\n /**\n * Render the property editor form\n */\n private renderPropertyEditor() {\n const hasProperties = this.componentMeta && this.componentMeta.attributes.length > 0;\n\n return (\n <div class=\"property-editor-container\">\n {hasProperties ? (\n <form class=\"property-editor\" onSubmit={e => e.preventDefault()}>\n {this.componentMeta!.attributes.map(attr => this.renderPropertyField(attr))}\n </form>\n ) : (\n <p class=\"no-properties\">No editable properties</p>\n )}\n <div class=\"property-editor-actions\">\n <le-button\n type=\"button\"\n variant=\"outlined\"\n color=\"danger\"\n full-width\n onClick={() => this.deleteComponent()}\n >\n <span slot=\"icon-start\">🗑️</span>\n <span>Delete Component</span>\n </le-button>\n </div>\n </div>\n );\n }\n\n /**\n * Render a single property field based on its type\n */\n private renderPropertyField(attr: AttributeMetadata) {\n const value = this.propertyValues[attr.name];\n const type = attr.type?.text || 'string';\n\n // Check if type is a union of string literals (e.g., \"'default' | 'outlined' | 'elevated'\")\n const enumMatch = type.match(/^'[^']+'/);\n if (enumMatch) {\n const options = type.split('|').map(opt => opt.trim().replace(/'/g, ''));\n return (\n <div class=\"property-field\">\n <label htmlFor={`prop-${attr.name}`}>\n {attr.name}\n {attr.description && <span class=\"property-hint\">{attr.description}</span>}\n </label>\n <le-select\n options={[...options.map(opt => ({ label: opt, value: opt }))]}\n full-width\n value={value ?? attr.default?.replace(/'/g, '')}\n placeholder={attr.default?.replace(/'/g, '')}\n onLeChange={(e: CustomEvent<LeOptionSelectDetail>) =>\n this.handlePropertyChange(attr.name, e.detail.value, type)\n }\n ></le-select>\n </div>\n );\n }\n\n // Boolean type\n if (type === 'boolean') {\n return (\n <div class=\"property-field property-field--checkbox\">\n <le-checkbox\n name={`prop-${attr.name}`}\n checked={value === true || value === ''}\n onChange={e =>\n this.handlePropertyChange(attr.name, (e.target as HTMLInputElement).checked, type)\n }\n >\n {attr.name}\n {attr.description && <div slot=\"description\">{attr.description}</div>}\n </le-checkbox>\n </div>\n );\n }\n\n // Number type\n if (type === 'number') {\n return (\n <div class=\"property-field\">\n <label htmlFor={`prop-${attr.name}`}>\n {attr.name}\n {attr.description && <span class=\"property-hint\">{attr.description}</span>}\n </label>\n <input\n type=\"number\"\n id={`prop-${attr.name}`}\n value={value ?? ''}\n placeholder={attr.default}\n onChange={e =>\n this.handlePropertyChange(attr.name, (e.target as HTMLInputElement).value, type)\n }\n />\n </div>\n );\n }\n\n // Default: string/text input\n return (\n <div class=\"property-field\">\n <le-string-input\n name={`prop-${attr.name}`}\n label={attr.name}\n value={value ?? ''}\n placeholder={attr.default?.replace(/'/g, '')}\n onChange={(e: any) => this.handlePropertyChange(attr.name, e.detail.value, type)}\n >\n <span slot=\"description\">{attr.description}</span>\n </le-string-input>\n </div>\n );\n }\n\n render() {\n const name = this.displayName || this.formatDisplayName(this.component);\n\n // In default mode, just pass through content with host classes\n if (!this.adminMode) {\n return (\n <Host class={classnames(this.component, this.hostClass)} style={this.hostStyle}>\n <slot></slot>\n </Host>\n );\n }\n\n // In admin mode, show wrapper with header and settings\n return (\n <Host class={classnames(this.component, this.hostClass, 'admin-mode')} style={this.hostStyle}>\n <div class=\"le-component-wrapper\">\n <div class=\"le-component-header\">\n <span class=\"le-component-name\">{name}</span>\n <le-popover\n popoverTitle={`${name} Settings`}\n position=\"right\"\n align=\"start\"\n min-width=\"300px\"\n mode=\"default\"\n >\n <le-button\n type=\"button\"\n class=\"le-component-button\"\n slot=\"trigger\"\n variant=\"clear\"\n size=\"small\"\n aria-label=\"Edit component properties\"\n icon-only\n >\n <span class=\"le-component-trigger\" slot=\"icon-only\">\n ⚙\n </span>\n </le-button>\n {this.renderPropertyEditor()}\n </le-popover>\n </div>\n <div class=\"le-component-content\">\n <slot></slot>\n </div>\n </div>\n </Host>\n );\n }\n}\n\n/**\n * Type definitions for component metadata\n */\ninterface ComponentMetadata {\n tagName: string;\n description?: string;\n attributes: AttributeMetadata[];\n}\n\ninterface AttributeMetadata {\n name: string;\n fieldName?: string;\n description?: string;\n default?: string;\n type?: {\n text: string;\n };\n}\n"]}
@@ -0,0 +1,12 @@
1
+ :host {
2
+ display: inline-flex;
3
+ min-width: 0;
4
+ }
5
+
6
+ .title {
7
+ font: inherit;
8
+ min-width: 0;
9
+ white-space: nowrap;
10
+ overflow: hidden;
11
+ text-overflow: ellipsis;
12
+ }
@@ -0,0 +1,130 @@
1
+ import { h, Host } from "@stencil/core";
2
+ /**
3
+ * Shows a "smart" header title based on what has scrolled out of view.
4
+ *
5
+ * When `selector` matches multiple elements, the title becomes the last element
6
+ * (top-to-bottom) that has fully scrolled out above the viewport.
7
+ *
8
+ * @slot - Optional fallback content if no watched title is active
9
+ *
10
+ * @csspart title - The rendered title
11
+ *
12
+ * @cmsEditable true
13
+ * @cmsCategory Layout
14
+ */
15
+ export class LeCurrentHeading {
16
+ el;
17
+ /** CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`). */
18
+ selector = '';
19
+ activeText = null;
20
+ componentWillLoad() {
21
+ this.updateActiveTitle();
22
+ }
23
+ onSelectorChange() {
24
+ this.updateActiveTitle();
25
+ }
26
+ onScroll() {
27
+ this.updateActiveTitle();
28
+ }
29
+ onResize() {
30
+ this.updateActiveTitle();
31
+ }
32
+ updateActiveTitle() {
33
+ if (typeof window === 'undefined')
34
+ return;
35
+ const selector = (this.selector ?? '').trim();
36
+ if (!selector) {
37
+ this.activeText = null;
38
+ return;
39
+ }
40
+ let elements = [];
41
+ try {
42
+ elements = Array.from(document.querySelectorAll(selector));
43
+ }
44
+ catch {
45
+ this.activeText = null;
46
+ return;
47
+ }
48
+ // Pick the last element that is fully above the viewport.
49
+ let nextText = null;
50
+ for (const element of elements) {
51
+ const rect = element.getBoundingClientRect();
52
+ if (rect.height > 0 && rect.bottom <= 0) {
53
+ const t = (element.textContent ?? '').trim();
54
+ if (t)
55
+ nextText = t;
56
+ }
57
+ }
58
+ // Do not create oscillations: update only when the computed title changes.
59
+ if (nextText !== this.activeText) {
60
+ this.activeText = nextText;
61
+ }
62
+ }
63
+ render() {
64
+ return (h(Host, { key: 'e6b473d3633eb8f194edf19e88850390f4319929' }, this.activeText ? (h("span", { class: "title", part: "title" }, this.activeText)) : (h("slot", null))));
65
+ }
66
+ static get is() { return "le-current-heading"; }
67
+ static get encapsulation() { return "shadow"; }
68
+ static get originalStyleUrls() {
69
+ return {
70
+ "$": ["le-current-heading.css"]
71
+ };
72
+ }
73
+ static get styleUrls() {
74
+ return {
75
+ "$": ["le-current-heading.css"]
76
+ };
77
+ }
78
+ static get properties() {
79
+ return {
80
+ "selector": {
81
+ "type": "string",
82
+ "mutable": false,
83
+ "complexType": {
84
+ "original": "string",
85
+ "resolved": "string",
86
+ "references": {}
87
+ },
88
+ "required": false,
89
+ "optional": false,
90
+ "docs": {
91
+ "tags": [],
92
+ "text": "CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`)."
93
+ },
94
+ "getter": false,
95
+ "setter": false,
96
+ "reflect": false,
97
+ "attribute": "selector",
98
+ "defaultValue": "''"
99
+ }
100
+ };
101
+ }
102
+ static get states() {
103
+ return {
104
+ "activeText": {}
105
+ };
106
+ }
107
+ static get elementRef() { return "el"; }
108
+ static get watchers() {
109
+ return [{
110
+ "propName": "selector",
111
+ "methodName": "onSelectorChange"
112
+ }];
113
+ }
114
+ static get listeners() {
115
+ return [{
116
+ "name": "scroll",
117
+ "method": "onScroll",
118
+ "target": "window",
119
+ "capture": false,
120
+ "passive": true
121
+ }, {
122
+ "name": "resize",
123
+ "method": "onResize",
124
+ "target": "window",
125
+ "capture": false,
126
+ "passive": true
127
+ }];
128
+ }
129
+ }
130
+ //# sourceMappingURL=le-current-heading.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"le-current-heading.js","sourceRoot":"","sources":["../../../src/components/le-current-heading/le-current-heading.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAExF;;;;;;;;;;;;GAYG;AAMH,MAAM,OAAO,gBAAgB;IAChB,EAAE,CAAc;IAE3B,qFAAqF;IACpD,QAAQ,GAAW,EAAE,CAAC;IAEtC,UAAU,GAAkB,IAAI,CAAC;IAElD,iBAAiB;QACf,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAGS,gBAAgB;QACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAGS,QAAQ;QAChB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAGS,QAAQ;QAChB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAEO,iBAAiB;QACvB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,QAAQ,GAAc,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,OAAO;QACT,CAAC;QAED,0DAA0D;QAC1D,IAAI,QAAQ,GAAkB,IAAI,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAI,OAAuB,CAAC,qBAAqB,EAAE,CAAC;YAC9D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACxC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,IAAI,CAAC;oBAAE,QAAQ,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,IAAI,QAAQ,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACjC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,CACL,EAAC,IAAI,uDACF,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CACjB,YAAM,KAAK,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,IAC7B,IAAI,CAAC,UAAU,CACX,CACR,CAAC,CAAC,CAAC,CACF,eAAa,CACd,CACI,CACR,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Element, h, Host, Listen, Prop, State, Watch } from '@stencil/core';\n\n/**\n * Shows a \"smart\" header title based on what has scrolled out of view.\n *\n * When `selector` matches multiple elements, the title becomes the last element\n * (top-to-bottom) that has fully scrolled out above the viewport.\n *\n * @slot - Optional fallback content if no watched title is active\n *\n * @csspart title - The rendered title\n *\n * @cmsEditable true\n * @cmsCategory Layout\n */\n@Component({\n tag: 'le-current-heading',\n styleUrl: 'le-current-heading.css',\n shadow: true,\n})\nexport class LeCurrentHeading {\n @Element() el: HTMLElement;\n\n /** CSS selector for page title/headings to watch (e.g. `.page-title`, `main h2`). */\n @Prop({ attribute: 'selector' }) selector: string = '';\n\n @State() private activeText: string | null = null;\n\n componentWillLoad() {\n this.updateActiveTitle();\n }\n\n @Watch('selector')\n protected onSelectorChange() {\n this.updateActiveTitle();\n }\n\n @Listen('scroll', { target: 'window', passive: true })\n protected onScroll() {\n this.updateActiveTitle();\n }\n\n @Listen('resize', { target: 'window', passive: true })\n protected onResize() {\n this.updateActiveTitle();\n }\n\n private updateActiveTitle() {\n if (typeof window === 'undefined') return;\n const selector = (this.selector ?? '').trim();\n if (!selector) {\n this.activeText = null;\n return;\n }\n\n let elements: Element[] = [];\n try {\n elements = Array.from(document.querySelectorAll(selector));\n } catch {\n this.activeText = null;\n return;\n }\n\n // Pick the last element that is fully above the viewport.\n let nextText: string | null = null;\n for (const element of elements) {\n const rect = (element as HTMLElement).getBoundingClientRect();\n if (rect.height > 0 && rect.bottom <= 0) {\n const t = (element.textContent ?? '').trim();\n if (t) nextText = t;\n }\n }\n\n // Do not create oscillations: update only when the computed title changes.\n if (nextText !== this.activeText) {\n this.activeText = nextText;\n }\n }\n\n render() {\n return (\n <Host>\n {this.activeText ? (\n <span class=\"title\" part=\"title\">\n {this.activeText}\n </span>\n ) : (\n <slot></slot>\n )}\n </Host>\n );\n }\n}\n"]}
@@ -45,6 +45,10 @@ le-popover::part(content) {
45
45
  letter-spacing: 0.05em;
46
46
  }
47
47
 
48
+ .dropdown-list {
49
+ text-align: initial;
50
+ }
51
+
48
52
  /* Separator */
49
53
  .dropdown-separator {
50
54
  height: 1px;
@@ -339,7 +339,7 @@ export class LeDropdownBase {
339
339
  }
340
340
  render() {
341
341
  const dropdownWidth = this.width || (this.triggerWidth ? `${this.triggerWidth}px` : undefined);
342
- return (h(Host, { key: 'c074cbfbc9a802ed01935b27baa6d0074d87c2e1' }, h("le-popover", { key: 'c5ff7f61f81df0f482e6a809a85f29ac73674de6', ref: el => (this.popoverEl = el), position: "bottom", align: "start", showClose: false, closeOnClickOutside: this.closeOnClickOutside, closeOnEscape: true, offset: 4, width: dropdownWidth, minWidth: "150px", "trigger-full-width": this.fullWidth, onLePopoverOpen: this.handlePopoverOpen, onLePopoverClose: this.handlePopoverClose }, h("slot", { key: 'b5ce8dba5357be102e282f10d0041cdd5ee11cb4', name: "trigger", slot: "trigger" }), h("slot", { key: '2534ee79fab3b7a1a44c61ab7e977c6f2f2be4d7', name: "header" }), h("div", { key: 'fd37d09cca2c96557030df201e095fab7a441fd9', class: "dropdown-list", role: "listbox", "aria-multiselectable": this.multiple ? 'true' : undefined, ref: el => (this.listEl = el), style: { maxHeight: this.maxHeight } }, this.renderOptions()))));
342
+ return (h(Host, { key: '838bef3556e494770fbb34cbff69c782ca717fe4' }, h("le-popover", { key: 'd72576e799c6cc065d3b0f3f1b918e84a7c5f690', ref: el => (this.popoverEl = el), position: "bottom", align: "start", showClose: false, closeOnClickOutside: this.closeOnClickOutside, closeOnEscape: true, offset: 4, width: dropdownWidth, minWidth: "150px", "trigger-full-width": this.fullWidth, onLePopoverOpen: this.handlePopoverOpen, onLePopoverClose: this.handlePopoverClose }, h("slot", { key: 'fbe84a553a126ad34f3ea159b182f825a065d1f6', name: "trigger", slot: "trigger" }), h("slot", { key: '957ac9208cdfe8be96a15979853e0b5cfdfc756f', name: "header" }), h("div", { key: '8c15f620b55035191979aca56514771c860051e3', class: "dropdown-list", role: "listbox", "aria-multiselectable": this.multiple ? 'true' : undefined, ref: el => (this.listEl = el), style: { maxHeight: this.maxHeight } }, this.renderOptions()))));
343
343
  }
344
344
  static get is() { return "le-dropdown-base"; }
345
345
  static get encapsulation() { return "shadow"; }