le-kit 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.ts +33 -0
- package/dist/components/le-box.d.ts +11 -0
- package/dist/components/le-button.d.ts +11 -0
- package/dist/components/le-card.d.ts +11 -0
- package/dist/components/le-checkbox.d.ts +11 -0
- package/dist/components/le-component.d.ts +11 -0
- package/dist/components/le-number-input.d.ts +11 -0
- package/dist/components/le-popover.d.ts +11 -0
- package/dist/components/le-popup.d.ts +11 -0
- package/dist/components/le-round-progress.d.ts +11 -0
- package/dist/components/le-slot.d.ts +11 -0
- package/dist/components/le-stack.d.ts +11 -0
- package/dist/components/le-string-input.d.ts +11 -0
- package/dist/components/le-text.d.ts +11 -0
- package/dist/components/le-turntable.d.ts +11 -0
- package/dist/core/cjs/{index-BsRb_UTe.js → index-B0mg71He.js} +6 -6
- package/dist/core/cjs/index-B0mg71He.js.map +1 -0
- package/dist/core/cjs/index.cjs.js +2 -2
- package/dist/core/cjs/le-box.cjs.entry.js +2 -2
- package/dist/core/cjs/le-button.cjs.entry.js +2 -2
- package/dist/core/cjs/le-card.cjs.entry.js +2 -2
- package/dist/core/cjs/le-checkbox.cjs.entry.js +2 -2
- package/dist/core/cjs/le-kit.cjs.js +1 -1
- package/dist/core/cjs/le-number-input.cjs.entry.js +2 -2
- package/dist/core/cjs/le-popover.cjs.entry.js +1 -1
- package/dist/core/cjs/le-popup.cjs.entry.js +1 -1
- package/dist/core/cjs/le-round-progress.cjs.entry.js +1 -1
- package/dist/core/cjs/le-stack.cjs.entry.js +2 -2
- package/dist/core/cjs/le-string-input.cjs.entry.js +2 -2
- package/dist/core/cjs/le-text.cjs.entry.js +2 -2
- package/dist/core/cjs/le-turntable.cjs.entry.js +1 -1
- package/dist/core/cjs/loader.cjs.js +1 -1
- package/dist/{cjs/utils-DqhadIxH.js → core/cjs/utils-jdqP71LP.js} +3 -3
- package/dist/core/cjs/{utils-nsP8_w8_.js.map → utils-jdqP71LP.js.map} +1 -1
- package/dist/core/collection/global/app.js +4 -4
- package/dist/core/collection/global/app.js.map +1 -1
- package/dist/core/components/index.d.ts +33 -0
- package/dist/{esm → core/components}/index.js +9 -2
- package/dist/core/components/index.js.map +1 -0
- package/dist/core/components/le-box.d.ts +11 -0
- package/dist/{cjs/le-box.cjs.entry.js → core/components/le-box.js} +87 -14
- package/dist/core/components/le-box.js.map +1 -0
- package/dist/core/components/le-button.d.ts +11 -0
- package/dist/core/components/le-button.js +9 -0
- package/dist/core/components/le-button.js.map +1 -0
- package/dist/{esm/le-button_6.entry.js → core/components/le-button2.js} +919 -972
- package/dist/core/components/le-button2.js.map +1 -0
- package/dist/core/components/le-card.d.ts +11 -0
- package/dist/core/components/le-card.js +84 -0
- package/dist/core/components/le-card.js.map +1 -0
- package/dist/core/components/le-checkbox.d.ts +11 -0
- package/dist/core/components/le-checkbox.js +9 -0
- package/dist/core/components/le-checkbox.js.map +1 -0
- package/dist/core/components/le-component.d.ts +11 -0
- package/dist/core/components/le-component.js +9 -0
- package/dist/core/components/le-component.js.map +1 -0
- package/dist/core/components/le-number-input.d.ts +11 -0
- package/dist/{cjs/le-number-input.cjs.entry.js → core/components/le-number-input.js} +85 -15
- package/dist/core/components/le-number-input.js.map +1 -0
- package/dist/core/components/le-popover.d.ts +11 -0
- package/dist/core/components/le-popover.js +9 -0
- package/dist/core/components/le-popover.js.map +1 -0
- package/dist/{collection/components/le-popover/le-popover.js → core/components/le-popover2.js} +49 -360
- package/dist/core/components/le-popover2.js.map +1 -0
- package/dist/core/components/le-popup.d.ts +11 -0
- package/dist/{cjs/le-popup.cjs.entry.js → core/components/le-popup.js} +88 -21
- package/dist/core/components/le-popup.js.map +1 -0
- package/dist/core/components/le-round-progress.d.ts +11 -0
- package/dist/{cjs/le-round-progress.cjs.entry.js → core/components/le-round-progress.js} +43 -14
- package/dist/core/components/le-round-progress.js.map +1 -0
- package/dist/core/components/le-slot.d.ts +11 -0
- package/dist/core/components/le-slot.js +9 -0
- package/dist/core/components/le-slot.js.map +1 -0
- package/dist/core/components/le-stack.d.ts +11 -0
- package/dist/{cjs/le-stack.cjs.entry.js → core/components/le-stack.js} +78 -14
- package/dist/core/components/le-stack.js.map +1 -0
- package/dist/core/components/le-string-input.d.ts +11 -0
- package/dist/core/components/le-string-input.js +9 -0
- package/dist/core/components/le-string-input.js.map +1 -0
- package/dist/core/components/le-text.d.ts +11 -0
- package/dist/{cjs/le-text.cjs.entry.js → core/components/le-text.js} +80 -16
- package/dist/core/components/le-text.js.map +1 -0
- package/dist/core/components/le-turntable.d.ts +11 -0
- package/dist/{cjs/le-turntable.cjs.entry.js → core/components/le-turntable.js} +37 -12
- package/dist/core/components/le-turntable.js.map +1 -0
- package/dist/core/components/utils.js +310 -0
- package/dist/core/components/utils.js.map +1 -0
- package/dist/core/esm/{index-CJ-z5Zj1.js → index-SKsXnjWI.js} +6 -6
- package/dist/core/{le-kit/p-CJ-z5Zj1.js.map → esm/index-SKsXnjWI.js.map} +1 -1
- package/dist/core/esm/index.js +2 -2
- package/dist/core/esm/le-box.entry.js +2 -2
- package/dist/core/esm/le-button.entry.js +2 -2
- package/dist/core/esm/le-card.entry.js +2 -2
- package/dist/core/esm/le-checkbox.entry.js +2 -2
- package/dist/core/esm/le-kit.js +2 -2
- package/dist/core/esm/le-number-input.entry.js +2 -2
- package/dist/core/esm/le-popover.entry.js +1 -1
- package/dist/core/esm/le-popup.entry.js +1 -1
- package/dist/core/esm/le-round-progress.entry.js +1 -1
- package/dist/core/esm/le-stack.entry.js +2 -2
- package/dist/core/esm/le-string-input.entry.js +2 -2
- package/dist/core/esm/le-text.entry.js +2 -2
- package/dist/core/esm/le-turntable.entry.js +1 -1
- package/dist/core/esm/loader.js +2 -2
- package/dist/{esm/utils-Cf7fMI0j.js → core/esm/utils-DZdP1JiG.js} +3 -3
- package/dist/core/esm/{utils-Bxmld82M.js.map → utils-DZdP1JiG.js.map} +1 -1
- package/dist/core/le-kit/index.esm.js +1 -1
- package/dist/core/le-kit/le-kit.esm.js +1 -1
- package/dist/core/le-kit/p--VxUdzYV.js +2 -0
- package/dist/core/le-kit/{p-Drz36PDp.js.map → p--VxUdzYV.js.map} +1 -1
- package/dist/core/le-kit/{p-2ac4789a.entry.js → p-189cb775.entry.js} +2 -2
- package/dist/core/le-kit/{p-556086ca.entry.js → p-35c1d413.entry.js} +2 -2
- package/dist/core/le-kit/{p-aa6e906f.entry.js → p-4f133e72.entry.js} +2 -2
- package/dist/core/le-kit/{p-df552906.entry.js → p-55f70091.entry.js} +2 -2
- package/dist/core/le-kit/{p-e0861e82.entry.js → p-5fd7b23a.entry.js} +2 -2
- package/dist/core/le-kit/{p-5ef81068.entry.js → p-6e414a5c.entry.js} +2 -2
- package/dist/core/le-kit/{p-d75214f9.entry.js → p-7b121ca7.entry.js} +2 -2
- package/dist/core/le-kit/{p-45eace7c.entry.js → p-8c81fa95.entry.js} +2 -2
- package/dist/core/le-kit/{p-257495cc.entry.js → p-9aa81442.entry.js} +2 -2
- package/dist/core/le-kit/p-SKsXnjWI.js +3 -0
- package/dist/core/le-kit/p-SKsXnjWI.js.map +1 -0
- package/dist/core/le-kit/{p-66d35f48.entry.js → p-a9d05ef6.entry.js} +2 -2
- package/dist/core/le-kit/{p-73682c5e.entry.js → p-b2bd2a80.entry.js} +2 -2
- package/dist/core/le-kit/{p-0308bd1f.entry.js → p-ccac9611.entry.js} +2 -2
- package/dist/core/types/global/app.d.ts +4 -4
- package/dist/le-kit/assets/custom-elements.json +1230 -1230
- package/dist/le-kit/index-CAY3Hk_i.js +4559 -0
- package/dist/le-kit/index-CAY3Hk_i.js.map +1 -0
- package/dist/le-kit/index.esm.js +116 -2
- package/dist/le-kit/index.esm.js.map +1 -1
- package/dist/{esm → le-kit}/le-box.entry.js +3 -3
- package/dist/le-kit/le-button.entry.esm.js.map +1 -0
- package/dist/le-kit/le-button.entry.js +90 -0
- package/dist/{esm → le-kit}/le-card.entry.js +3 -3
- package/dist/le-kit/le-checkbox.entry.esm.js.map +1 -0
- package/dist/le-kit/le-checkbox.entry.js +59 -0
- package/dist/le-kit/le-component.entry.esm.js.map +1 -0
- package/dist/{collection/components/le-component/le-component.js → le-kit/le-component.entry.js} +19 -138
- package/dist/le-kit/le-kit.css +1010 -1
- package/dist/le-kit/le-kit.esm.js +48 -2
- package/dist/le-kit/le-kit.esm.js.map +1 -1
- package/dist/{esm → le-kit}/le-number-input.entry.js +5 -5
- package/dist/le-kit/le-popover.entry.esm.js.map +1 -0
- package/dist/le-kit/le-popover.entry.js +346 -0
- package/dist/{esm → le-kit}/le-popup.entry.js +6 -6
- package/dist/{esm → le-kit}/le-round-progress.entry.js +2 -2
- package/dist/le-kit/le-slot.entry.esm.js.map +1 -0
- package/dist/{collection/components/le-slot/le-slot.js → le-kit/le-slot.entry.js} +20 -273
- package/dist/{esm → le-kit}/le-stack.entry.js +3 -3
- package/dist/le-kit/le-string-input.entry.esm.js.map +1 -0
- package/dist/le-kit/le-string-input.entry.js +93 -0
- package/dist/{esm → le-kit}/le-text.entry.js +3 -3
- package/dist/{esm → le-kit}/le-turntable.entry.js +2 -2
- package/dist/{core/esm/utils-Bxmld82M.js → le-kit/utils-cwSNy7ZS.js} +3 -3
- package/dist/{esm/utils-Cf7fMI0j.js.map → le-kit/utils-cwSNy7ZS.js.map} +1 -1
- package/dist/types/global/app.d.ts +4 -4
- package/package.json +4 -5
- package/readme.md +2 -2
- package/custom-elements.json +0 -4305
- package/dist/cjs/index-o1DRKw1g.js +0 -1842
- package/dist/cjs/index-o1DRKw1g.js.map +0 -1
- package/dist/cjs/index.cjs.js +0 -119
- package/dist/cjs/index.cjs.js.map +0 -1
- package/dist/cjs/le-box.entry.cjs.js.map +0 -1
- package/dist/cjs/le-button.le-checkbox.le-component.le-popover.le-slot.le-string-input.entry.cjs.js.map +0 -1
- package/dist/cjs/le-button_6.cjs.entry.js +0 -1206
- package/dist/cjs/le-card.cjs.entry.js +0 -29
- package/dist/cjs/le-card.entry.cjs.js.map +0 -1
- package/dist/cjs/le-kit.cjs.js +0 -25
- package/dist/cjs/le-kit.cjs.js.map +0 -1
- package/dist/cjs/le-number-input.entry.cjs.js.map +0 -1
- package/dist/cjs/le-popup.entry.cjs.js.map +0 -1
- package/dist/cjs/le-round-progress.entry.cjs.js.map +0 -1
- package/dist/cjs/le-stack.entry.cjs.js.map +0 -1
- package/dist/cjs/le-text.entry.cjs.js.map +0 -1
- package/dist/cjs/le-turntable.entry.cjs.js.map +0 -1
- package/dist/cjs/loader.cjs.js +0 -13
- package/dist/cjs/loader.cjs.js.map +0 -1
- package/dist/cjs/utils-DqhadIxH.js.map +0 -1
- package/dist/collection/assets/custom-elements.json +0 -4305
- package/dist/collection/collection-manifest.json +0 -26
- package/dist/collection/components/le-box/le-box.default.css +0 -37
- package/dist/collection/components/le-box/le-box.js +0 -614
- package/dist/collection/components/le-box/le-box.js.map +0 -1
- package/dist/collection/components/le-button/le-button.default.css +0 -263
- package/dist/collection/components/le-button/le-button.js +0 -368
- package/dist/collection/components/le-button/le-button.js.map +0 -1
- package/dist/collection/components/le-card/le-card.default.css +0 -74
- package/dist/collection/components/le-card/le-card.js +0 -102
- package/dist/collection/components/le-card/le-card.js.map +0 -1
- package/dist/collection/components/le-checkbox/le-checkbox.css +0 -93
- package/dist/collection/components/le-checkbox/le-checkbox.js +0 -192
- package/dist/collection/components/le-checkbox/le-checkbox.js.map +0 -1
- package/dist/collection/components/le-component/le-component.css +0 -189
- package/dist/collection/components/le-component/le-component.js.map +0 -1
- package/dist/collection/components/le-number-input/le-number-input.css +0 -135
- package/dist/collection/components/le-number-input/le-number-input.js +0 -515
- package/dist/collection/components/le-number-input/le-number-input.js.map +0 -1
- package/dist/collection/components/le-popover/le-popover.css +0 -143
- package/dist/collection/components/le-popover/le-popover.js.map +0 -1
- package/dist/collection/components/le-popup/le-popup.api.js +0 -101
- package/dist/collection/components/le-popup/le-popup.api.js.map +0 -1
- package/dist/collection/components/le-popup/le-popup.css +0 -222
- package/dist/collection/components/le-popup/le-popup.js +0 -596
- package/dist/collection/components/le-popup/le-popup.js.map +0 -1
- package/dist/collection/components/le-round-progress/le-round-progress.css +0 -34
- package/dist/collection/components/le-round-progress/le-round-progress.js +0 -184
- package/dist/collection/components/le-round-progress/le-round-progress.js.map +0 -1
- package/dist/collection/components/le-slot/le-slot.default.css +0 -222
- package/dist/collection/components/le-slot/le-slot.js.map +0 -1
- package/dist/collection/components/le-stack/le-stack.default.css +0 -37
- package/dist/collection/components/le-stack/le-stack.js +0 -389
- package/dist/collection/components/le-stack/le-stack.js.map +0 -1
- package/dist/collection/components/le-string-input/le-string-input.css +0 -83
- package/dist/collection/components/le-string-input/le-string-input.js +0 -359
- package/dist/collection/components/le-string-input/le-string-input.js.map +0 -1
- package/dist/collection/components/le-text/le-text.default.css +0 -169
- package/dist/collection/components/le-text/le-text.js +0 -475
- package/dist/collection/components/le-text/le-text.js.map +0 -1
- package/dist/collection/components/le-turntable/le-turntable.css +0 -10
- package/dist/collection/components/le-turntable/le-turntable.js +0 -210
- package/dist/collection/components/le-turntable/le-turntable.js.map +0 -1
- package/dist/collection/global/app.js +0 -167
- package/dist/collection/global/app.js.map +0 -1
- package/dist/collection/index.js +0 -15
- package/dist/collection/index.js.map +0 -1
- package/dist/collection/types/blocks.js +0 -115
- package/dist/collection/types/blocks.js.map +0 -1
- package/dist/collection/types/options.js +0 -2
- package/dist/collection/types/options.js.map +0 -1
- package/dist/collection/utils/utils.js +0 -141
- package/dist/collection/utils/utils.js.map +0 -1
- package/dist/core/cjs/index-BsRb_UTe.js.map +0 -1
- package/dist/core/cjs/utils-nsP8_w8_.js +0 -152
- package/dist/core/esm/index-CJ-z5Zj1.js.map +0 -1
- package/dist/core/le-kit/p-CJ-z5Zj1.js +0 -3
- package/dist/core/le-kit/p-Drz36PDp.js +0 -2
- package/dist/docs.d.ts +0 -443
- package/dist/docs.json +0 -5185
- package/dist/esm/index-CwNQ1GTa.js +0 -1824
- package/dist/esm/index-CwNQ1GTa.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/le-box.entry.js.map +0 -1
- package/dist/esm/le-button.le-checkbox.le-component.le-popover.le-slot.le-string-input.entry.js.map +0 -1
- package/dist/esm/le-card.entry.js.map +0 -1
- package/dist/esm/le-kit.js +0 -21
- package/dist/esm/le-kit.js.map +0 -1
- package/dist/esm/le-number-input.entry.js.map +0 -1
- package/dist/esm/le-popup.entry.js.map +0 -1
- package/dist/esm/le-round-progress.entry.js.map +0 -1
- package/dist/esm/le-stack.entry.js.map +0 -1
- package/dist/esm/le-text.entry.js.map +0 -1
- package/dist/esm/le-turntable.entry.js.map +0 -1
- package/dist/esm/loader.js +0 -11
- package/dist/esm/loader.js.map +0 -1
- package/dist/index.cjs.js +0 -1
- package/dist/index.js +0 -1
- package/dist/le-kit/le-button.le-checkbox.le-component.le-popover.le-slot.le-string-input.entry.esm.js.map +0 -1
- package/dist/le-kit/p-08dbcc25.entry.js +0 -2
- package/dist/le-kit/p-08dbcc25.entry.js.map +0 -1
- package/dist/le-kit/p-5dc35729.entry.js +0 -2
- package/dist/le-kit/p-5dc35729.entry.js.map +0 -1
- package/dist/le-kit/p-64374730.entry.js +0 -2
- package/dist/le-kit/p-64374730.entry.js.map +0 -1
- package/dist/le-kit/p-79ec6f7c.entry.js +0 -2
- package/dist/le-kit/p-79ec6f7c.entry.js.map +0 -1
- package/dist/le-kit/p-8daf3c7f.entry.js +0 -2
- package/dist/le-kit/p-8daf3c7f.entry.js.map +0 -1
- package/dist/le-kit/p-9c69235d.entry.js +0 -2
- package/dist/le-kit/p-9c69235d.entry.js.map +0 -1
- package/dist/le-kit/p-CwNQ1GTa.js +0 -3
- package/dist/le-kit/p-CwNQ1GTa.js.map +0 -1
- package/dist/le-kit/p-ad398acd.entry.js +0 -2
- package/dist/le-kit/p-ad398acd.entry.js.map +0 -1
- package/dist/le-kit/p-b8122ad6.entry.js +0 -2
- package/dist/le-kit/p-b8122ad6.entry.js.map +0 -1
- package/dist/le-kit/p-f9008505.entry.js +0 -2
- package/dist/le-kit/p-f9008505.entry.js.map +0 -1
- package/dist/le-kit/p-y3FECAx9.js +0 -2
- package/dist/le-kit/p-y3FECAx9.js.map +0 -1
- package/dist/themes/base.css +0 -89
- package/dist/themes/dark.css +0 -100
- package/dist/themes/default.css +0 -108
- package/dist/themes/gradient.css +0 -100
- package/dist/themes/index.css +0 -413
- package/dist/themes/minimal.css +0 -100
- package/dist/themes/warm.css +0 -100
- /package/dist/{collection → components}/themes/base.css +0 -0
- /package/dist/{collection → components}/themes/dark.css +0 -0
- /package/dist/{collection → components}/themes/default.css +0 -0
- /package/dist/{collection → components}/themes/gradient.css +0 -0
- /package/dist/{collection → components}/themes/index.css +0 -0
- /package/dist/{collection → components}/themes/minimal.css +0 -0
- /package/dist/{collection → components}/themes/warm.css +0 -0
- /package/dist/core/le-kit/{p-2ac4789a.entry.js.map → p-189cb775.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-556086ca.entry.js.map → p-35c1d413.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-aa6e906f.entry.js.map → p-4f133e72.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-df552906.entry.js.map → p-55f70091.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-e0861e82.entry.js.map → p-5fd7b23a.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-5ef81068.entry.js.map → p-6e414a5c.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-d75214f9.entry.js.map → p-7b121ca7.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-45eace7c.entry.js.map → p-8c81fa95.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-257495cc.entry.js.map → p-9aa81442.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-66d35f48.entry.js.map → p-a9d05ef6.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-73682c5e.entry.js.map → p-b2bd2a80.entry.js.map} +0 -0
- /package/dist/core/le-kit/{p-0308bd1f.entry.js.map → p-ccac9611.entry.js.map} +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/base.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/dark.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/default.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/gradient.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/index.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/minimal.css +0 -0
- /package/dist/le-kit/{themes → dist/components/themes}/warm.css +0 -0
|
@@ -1,1199 +1,1146 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { proxyCustomElement, HTMLElement, createEvent, h, getAssetPath, Host, Fragment } from '@stencil/core/internal/client';
|
|
2
|
+
import { h as classnames, o as observeModeChanges, f as getLeKitConfig } from './utils.js';
|
|
3
|
+
import { d as defineCustomElement$5 } from './le-popover2.js';
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const leStringInputCss = ":host{display:block;--le-input-bg:var(--le-color-surface, #ffffff);--le-input-color:var(--le-color-text-primary, #333333);--le-input-border:var(--le-border-width, 2px) solid var(--le-color-border-input, #007bff);--le-input-radius:var(--le-radius-sm, 4px);--le-input-padding:2px 6px;--le-input-height:1.5rem;--le-input-label-color:var(--le-color-text-primary, #333333);--le-input-desc-color:var(--le-color-text-secondary, #666666);--le-input-placeholder-color:#999999}.le-input-wrapper{display:flex;flex-direction:column;gap:2px}.le-input-label{display:block;font-size:0.9em;font-weight:500;color:var(--le-input-label-color);margin-bottom:2px}.le-input-container{position:relative;display:flex;align-items:center;background:var(--le-input-bg);border:var(--le-input-border);border-radius:var(--le-input-radius);transition:border-color 0.2s}.le-input-container:focus-within{outline:2px solid var(--le-color-focus);outline-offset:2px}:host([disabled]) .le-input-container{opacity:0.6;background-color:rgba(0,0,0,0.05);cursor:not-allowed}input{flex:1;min-height:var(--le-input-height);padding:var(--le-input-padding);border:none;background:transparent;color:var(--le-input-color);font-family:inherit;font-size:inherit;outline:none;width:100%}input::placeholder{color:var(--le-input-placeholder-color)}.icon-start,.icon-end{display:flex;align-items:center;justify-content:center;padding:0 8px;color:var(--le-input-desc-color)}.le-input-description{font-size:0.85em;color:var(--le-input-desc-color);margin-top:2px}.le-input-description::has(le-slot>slot[name=description]:empty){display:none}";
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const LeStringInput = /*@__PURE__*/ proxyCustomElement(class LeStringInput extends HTMLElement {
|
|
8
|
+
constructor(registerHost) {
|
|
9
|
+
super();
|
|
10
|
+
if (registerHost !== false) {
|
|
11
|
+
this.__registerHost();
|
|
12
|
+
}
|
|
13
|
+
this.__attachShadow();
|
|
14
|
+
this.leChange = createEvent(this, "change", 7);
|
|
15
|
+
this.leInput = createEvent(this, "input", 7);
|
|
10
16
|
}
|
|
11
|
-
get el() { return
|
|
17
|
+
get el() { return this; }
|
|
12
18
|
/**
|
|
13
19
|
* Mode of the popover should be 'default' for internal use
|
|
14
20
|
*/
|
|
15
21
|
mode;
|
|
16
22
|
/**
|
|
17
|
-
*
|
|
18
|
-
* @allowedValues solid | outlined | clear
|
|
23
|
+
* The value of the input
|
|
19
24
|
*/
|
|
20
|
-
|
|
25
|
+
value;
|
|
21
26
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @allowedValues primary | secondary | success | warning | danger | info
|
|
27
|
+
* The name of the input
|
|
24
28
|
*/
|
|
25
|
-
|
|
29
|
+
name;
|
|
26
30
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @allowedValues small | medium | large
|
|
31
|
+
* The type of the input (text, email, password, etc.)
|
|
29
32
|
*/
|
|
30
|
-
|
|
33
|
+
type = 'text';
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
35
|
+
* Label for the input
|
|
33
36
|
*/
|
|
34
|
-
|
|
37
|
+
label;
|
|
35
38
|
/**
|
|
36
|
-
*
|
|
39
|
+
* Icon for the start icon
|
|
37
40
|
*/
|
|
38
|
-
|
|
41
|
+
iconStart;
|
|
39
42
|
/**
|
|
40
|
-
*
|
|
43
|
+
* Icon for the end icon
|
|
41
44
|
*/
|
|
42
|
-
|
|
45
|
+
iconEnd;
|
|
43
46
|
/**
|
|
44
|
-
*
|
|
47
|
+
* Placeholder text
|
|
48
|
+
*/
|
|
49
|
+
placeholder;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the input is disabled
|
|
45
52
|
*/
|
|
46
53
|
disabled = false;
|
|
47
54
|
/**
|
|
48
|
-
*
|
|
49
|
-
* @allowedValues button | submit | reset
|
|
55
|
+
* Whether the input is read-only
|
|
50
56
|
*/
|
|
51
|
-
|
|
57
|
+
readonly = false;
|
|
52
58
|
/**
|
|
53
|
-
*
|
|
59
|
+
* External ID for linking with external systems
|
|
54
60
|
*/
|
|
55
|
-
|
|
61
|
+
externalId;
|
|
56
62
|
/**
|
|
57
|
-
*
|
|
63
|
+
* Emitted when the value changes (on blur or Enter)
|
|
58
64
|
*/
|
|
59
|
-
|
|
65
|
+
leChange;
|
|
60
66
|
/**
|
|
61
|
-
* Emitted when the
|
|
62
|
-
* This is a custom event that wraps the native click but ensures the target is the le-button.
|
|
67
|
+
* Emitted when the input value changes (on keystroke)
|
|
63
68
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.leClick.emit(event);
|
|
69
|
+
leInput;
|
|
70
|
+
handleInput = (ev) => {
|
|
71
|
+
const input = ev.target;
|
|
72
|
+
this.value = input.value;
|
|
73
|
+
this.leInput.emit({
|
|
74
|
+
value: this.value,
|
|
75
|
+
name: this.name,
|
|
76
|
+
externalId: this.externalId
|
|
77
|
+
});
|
|
74
78
|
};
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
handleChange = (ev) => {
|
|
80
|
+
const input = ev.target;
|
|
81
|
+
this.value = input.value;
|
|
82
|
+
this.leChange.emit({
|
|
83
|
+
value: this.value,
|
|
84
|
+
name: this.name,
|
|
85
|
+
externalId: this.externalId
|
|
81
86
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
};
|
|
88
|
+
handleClick = (ev) => {
|
|
89
|
+
ev.stopPropagation();
|
|
90
|
+
};
|
|
91
|
+
render() {
|
|
92
|
+
return (h("le-component", { key: 'd0c69370dae2d1fee5700954e4823d2a03a51331', component: "le-string-input", hostClass: classnames({ 'disabled': this.disabled }) }, h("div", { key: '4acae8d3c34da2a86970a616c493ff210d561f5f', class: "le-input-wrapper" }, this.label && (h("label", { key: '609191b45187b6b1a65d05cd594b149760ac6882', class: "le-input-label", htmlFor: this.name }, this.label)), h("div", { key: '36b4caff4468ac7421db03f811cb3ef4a622b001', class: "le-input-container" }, this.iconStart && (h("span", { key: '344f88887fe8270bbef7e26ec1ad5da9fae1f8e4', class: "icon-start" }, this.iconStart)), h("input", { key: '4ba7beeddd7fb3cf23d03e029d11a804764cdd6e', id: this.name, type: this.type, name: this.name, value: this.value, placeholder: this.placeholder, disabled: this.disabled, readOnly: this.readonly, onInput: this.handleInput, onChange: this.handleChange, onClick: this.handleClick }), this.iconEnd && (h("span", { key: '7cdd4b52c3e1a1b18b19e697bdb42431941bba01', class: "icon-end" }, this.iconEnd))), h("div", { key: '113a75aa413e4d95300aeaa97d1ce7a75cf68c7a', class: "le-input-description" }, h("le-slot", { key: '0b37fc14e6df68f6c44cf9001d63a70f019e1cc3', name: "description", type: "text", tag: "p", label: "Description" }, h("slot", { key: '2674056dc915fabdb4fcbcaa13294a116b9509a6', name: "description" }))))));
|
|
93
|
+
}
|
|
94
|
+
static get style() { return leStringInputCss; }
|
|
95
|
+
}, [769, "le-string-input", {
|
|
96
|
+
"mode": [1537],
|
|
97
|
+
"value": [1537],
|
|
98
|
+
"name": [1],
|
|
99
|
+
"type": [1],
|
|
100
|
+
"label": [1],
|
|
101
|
+
"iconStart": [1, "icon-start"],
|
|
102
|
+
"iconEnd": [1, "icon-end"],
|
|
103
|
+
"placeholder": [1],
|
|
104
|
+
"disabled": [4],
|
|
105
|
+
"readonly": [4],
|
|
106
|
+
"externalId": [1, "external-id"]
|
|
107
|
+
}]);
|
|
108
|
+
function defineCustomElement$4() {
|
|
109
|
+
if (typeof customElements === "undefined") {
|
|
110
|
+
return;
|
|
85
111
|
}
|
|
86
|
-
|
|
87
|
-
|
|
112
|
+
const components = ["le-string-input", "le-button", "le-checkbox", "le-component", "le-popover", "le-slot", "le-string-input"];
|
|
113
|
+
components.forEach(tagName => { switch (tagName) {
|
|
114
|
+
case "le-string-input":
|
|
115
|
+
if (!customElements.get(tagName)) {
|
|
116
|
+
customElements.define(tagName, LeStringInput);
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
case "le-button":
|
|
120
|
+
if (!customElements.get(tagName)) {
|
|
121
|
+
defineCustomElement();
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
case "le-checkbox":
|
|
125
|
+
if (!customElements.get(tagName)) {
|
|
126
|
+
defineCustomElement$1();
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
case "le-component":
|
|
130
|
+
if (!customElements.get(tagName)) {
|
|
131
|
+
defineCustomElement$2();
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
case "le-popover":
|
|
135
|
+
if (!customElements.get(tagName)) {
|
|
136
|
+
defineCustomElement$5();
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case "le-slot":
|
|
140
|
+
if (!customElements.get(tagName)) {
|
|
141
|
+
defineCustomElement$3();
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
case "le-string-input":
|
|
145
|
+
if (!customElements.get(tagName)) {
|
|
146
|
+
defineCustomElement$4();
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
} });
|
|
150
|
+
}
|
|
88
151
|
|
|
89
|
-
const
|
|
152
|
+
const leSlotDefaultCss = ":host{display:contents;--le-slot-border-color:#0088ff;--le-slot-bg-color:rgba(0, 136, 255, 0.05);--le-slot-header-bg:rgb(218, 238, 255);--le-slot-label-color:#0066cc;--le-slot-description-color:#666;--le-slot-required-color:#e53935;--le-slot-dropzone-min-height:20px;--le-slot-dropzone-border-color:#ccc}.le-slot-container,.le-slot-header,.le-slot-description,.le-slot-dropzone,.le-slot-input{display:none}.hidden-slot{display:none}:host(.admin-mode){display:block;flex:1}:host(.admin-mode) .le-slot-container{position:relative;display:flex;flex-direction:column;border:2px dashed var(--le-slot-border-color);border-radius:4px;background:var(--le-slot-bg-color);margin:4px 0}:host(.admin-mode) .le-slot-header{display:flex;align-items:center;gap:4px;padding:0 0 0 var(--le-spacing-1, 4px);background:var(--le-slot-header-bg);border-bottom:1px solid var(--le-slot-border-color);font-size:var(--le-font-size-xs, 11px);font-weight:400;text-transform:capitalize}:host(.admin-mode) .le-slot-header-no-label{justify-content:flex-end;height:16px;border:none;background-color:transparent}.le-slot-label{color:var(--le-slot-label-color);text-align:start;overflow:hidden;width:0;flex:1 1 0%}.le-slot-required{color:var(--le-slot-required-color);font-weight:bold}:host(.admin-mode) .le-slot-description{display:block;padding:4px 8px;font-size:12px;color:var(--le-slot-description-color);font-style:italic}:host(.admin-mode) .le-slot-description-icon{display:inline-block;font-size:9px;line-height:1;cursor:pointer;color:var(--le-slot-description-color)}:host(.admin-mode) .le-slot-dropzone{display:block;min-height:var(--le-slot-dropzone-min-height);padding:var(--le-spacing-1, 4px);position:relative}:host(.admin-mode) .le-slot-dropzone:empty::before{content:'Drop content here';display:flex;align-items:center;justify-content:center;position:absolute;inset:8px;border:2px dashed var(--le-slot-dropzone-border-color);border-radius:4px;color:#999;font-size:12px;pointer-events:none}:host(.admin-mode.drag-over) .le-slot-container{border-color:#00cc66;background:rgba(0, 204, 102, 0.1)}:host(.admin-mode.drag-over) .le-slot-dropzone:empty::before{border-color:#00cc66;color:#00cc66;content:'Release to drop'}:host(.admin-mode) .le-slot-input{display:block;padding:var(--le-spacing-1, 4px)}:host(.admin-mode) .le-slot-input input,:host(.admin-mode) .le-slot-input textarea{display:block;width:100%;padding:8px 10px;border:1px solid var(--le-slot-dropzone-border-color);border-radius:4px;font-family:inherit;font-size:14px;line-height:1.4;background:#fff;color:#333;box-sizing:border-box;transition:border-color 0.2s, box-shadow 0.2s}:host(.admin-mode) .le-slot-input input:focus,:host(.admin-mode) .le-slot-input textarea:focus{outline:none;border-color:var(--le-slot-border-color);box-shadow:0 0 0 3px rgba(0, 136, 255, 0.15)}:host(.admin-mode) .le-slot-input input::placeholder,:host(.admin-mode) .le-slot-input textarea::placeholder{color:#999}:host(.admin-mode) .le-slot-input textarea{resize:vertical;min-height:60px}:host(.admin-mode) .le-slot-input slot{display:none}.le-slot-invalid{color:var(--le-slot-required-color);font-size:10px;margin-left:auto;font-weight:normal;text-transform:none}:host(.admin-mode) .le-slot-input.has-error input,:host(.admin-mode) .le-slot-input.has-error textarea{border-color:var(--le-slot-required-color);background:rgba(229, 57, 53, 0.05)}:host(.admin-mode) .le-slot-input.has-error input:focus,:host(.admin-mode) .le-slot-input.has-error textarea:focus{border-color:var(--le-slot-required-color);box-shadow:0 0 0 3px rgba(229, 57, 53, 0.15)}.le-slot-add-btn{font-size:24px;line-height:0px;width:12px;height:12px}.le-slot-header-no-label .le-slot-add-btn{font-size:16px}.le-slot-button{width:20px;height:20px}:host(.admin-mode) .le-slot-header-no-label.le-slot-header-text{height:0}";
|
|
90
153
|
|
|
91
|
-
const
|
|
92
|
-
constructor(
|
|
93
|
-
|
|
94
|
-
|
|
154
|
+
const LeSlot = /*@__PURE__*/ proxyCustomElement(class LeSlot extends HTMLElement {
|
|
155
|
+
constructor(registerHost) {
|
|
156
|
+
super();
|
|
157
|
+
if (registerHost !== false) {
|
|
158
|
+
this.__registerHost();
|
|
159
|
+
}
|
|
160
|
+
this.__attachShadow();
|
|
161
|
+
this.leSlotChange = createEvent(this, "leSlotChange", 7);
|
|
95
162
|
}
|
|
96
|
-
get el() { return
|
|
163
|
+
get el() { return this; }
|
|
97
164
|
/**
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* Whether the checkbox is disabled
|
|
165
|
+
* The type of slot content.
|
|
166
|
+
* - `slot`: Default, shows a dropzone for components (default)
|
|
167
|
+
* - `text`: Shows a single-line text input
|
|
168
|
+
* - `textarea`: Shows a multi-line text area
|
|
103
169
|
*/
|
|
104
|
-
|
|
170
|
+
type = 'slot';
|
|
105
171
|
/**
|
|
106
|
-
* The name of the
|
|
172
|
+
* The name of the slot this placeholder represents.
|
|
173
|
+
* Should match the slot name in the parent component.
|
|
107
174
|
*/
|
|
108
|
-
name;
|
|
175
|
+
name = '';
|
|
109
176
|
/**
|
|
110
|
-
*
|
|
177
|
+
* Label to display in admin mode.
|
|
178
|
+
* If not provided, the slot name will be used.
|
|
111
179
|
*/
|
|
112
|
-
|
|
180
|
+
label;
|
|
113
181
|
/**
|
|
114
|
-
*
|
|
182
|
+
* Description of what content this slot accepts.
|
|
183
|
+
* Shown in admin mode to guide content editors.
|
|
115
184
|
*/
|
|
116
|
-
|
|
185
|
+
description;
|
|
117
186
|
/**
|
|
118
|
-
*
|
|
187
|
+
* Comma-separated list of allowed component tags for this slot.
|
|
188
|
+
* Used by CMS to filter available components.
|
|
189
|
+
*
|
|
190
|
+
* @example "le-card,le-button,le-text"
|
|
119
191
|
*/
|
|
120
|
-
|
|
121
|
-
handleChange = (event) => {
|
|
122
|
-
// We stop the internal button click from bubbling up
|
|
123
|
-
event.stopPropagation();
|
|
124
|
-
if (this.disabled) {
|
|
125
|
-
event.preventDefault();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
const input = event.target;
|
|
129
|
-
this.checked = input.checked;
|
|
130
|
-
this.leChange.emit({
|
|
131
|
-
checked: this.checked,
|
|
132
|
-
value: this.value,
|
|
133
|
-
name: this.name,
|
|
134
|
-
externalId: this.externalId
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
render() {
|
|
138
|
-
return (h("le-component", { key: '43399929e07835e0019d509803e50a151921fa72', component: "le-checkbox", hostClass: classnames({ 'disabled': this.disabled }) }, h("div", { key: '7ddbf2ac1690bb09082adfea70b9767c972d007a', class: "le-checkbox-wrapper" }, h("label", { key: '8eec4055c713e8b3b155695751b10bff64c9f903', class: "le-checkbox-label" }, h("span", { key: '2118b1cbe7911ff1674e522d723949d81cade185', class: "le-checkbox-input" }, h("input", { key: 'd0a30af5c14497fa6fa294c07ba74ae2e032481f', type: "checkbox", name: this.name, value: this.value, checked: this.checked, disabled: this.disabled, onChange: this.handleChange })), h("span", { key: '02cf9588431240039a53ee50e02b08ba5d63b974', class: "le-checkbox-text" }, h("le-slot", { key: 'e7d7b253deab72e627164eb72fc06109abfca6a5', name: "", type: "text", tag: "span" }, h("slot", { key: '1d8c443073e48848513a8a6d04cd7805a394e54e' })))), h("div", { key: '16c2c927dc0c0f7844a203a0628bf0e561009bd0', class: "le-checkbox-description" }, h("le-slot", { key: 'c6898ecc8992dce4786e68ab4b136bf5c3a4d3aa', name: "description", type: "text", tag: "div", label: "Description" }, h("slot", { key: '3342add8ed1400ab74681e445163eeb3dd415941', name: "description" }))))));
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
LeCheckbox.style = leCheckboxCss;
|
|
142
|
-
|
|
143
|
-
const leComponentCss = ":host{display:contents}:host(.admin-mode){display:block}.le-component-wrapper{position:relative;border:2px dashed var(--le-admin-border-color, #90caf9);border-radius:var(--le-radius-md, 8px);background:var(--le-admin-bg, rgba(144, 202, 249, 0.05));transition:border-color 0.2s ease, box-shadow 0.2s ease}.le-component-wrapper:hover{border-color:var(--le-admin-border-hover, #42a5f5);box-shadow:0 0 0 2px var(--le-admin-glow, rgba(66, 165, 245, 0.2))}.le-component-header{display:flex;align-items:center;justify-content:space-between;gap:var(--le-spacing-1, 4px);padding:0 0 0 var(--le-spacing-1, 4px);background:var(--le-admin-header-bg, rgba(144, 202, 249, 0.15));border-bottom:1px solid var(--le-admin-border-color, #90caf9);border-radius:var(--le-radius-md, 8px) var(--le-radius-md, 8px) 0 0;font-size:var(--le-font-size-xs, 11px)}.le-component-name{font-weight:var(--le-font-weight-medium, 500);color:var(--le-admin-text, #1976d2);text-transform:capitalize;text-align:start;overflow:hidden;width:0;flex:1 1 0%}.le-component-content{padding:var(--le-space-xs, 4px)}.le-component-trigger{font-size:24px;line-height:0px;width:12px;height:12px}.le-component-button{width:20px}.property-editor{display:flex;flex-direction:column;gap:var(--le-space-sm, 8px);max-width:380px}.property-field{display:flex;flex-direction:column;gap:var(--le-space-xs, 4px)}.property-field label{display:flex;flex-direction:column;gap:2px;font-size:var(--le-font-size-sm, 13px);font-weight:var(--le-font-weight-medium, 500);color:var(--le-color-text, #333)}.property-hint{font-size:var(--le-font-size-xs, 11px);font-weight:normal;color:var(--le-color-text-secondary, #666);line-height:1.3}.property-field input[type=\"text\"],.property-field input[type=\"number\"],.property-field select{padding:var(--le-space-xs, 4px) var(--le-space-sm, 8px);border:1px solid var(--le-color-border, #ddd);border-radius:var(--le-radius-md, 7px);font-size:var(--le-font-size-sm, 13px);font-family:inherit;background:var(--le-color-surface, #fff);color:var(--le-color-text, #333);transition:border-color 0.15s ease, box-shadow 0.15s ease}.property-field input:focus,.property-field select:focus{outline:none;border-color:var(--le-color-primary, #1976d2);box-shadow:0 0 0 2px var(--le-color-primary-light, rgba(25, 118, 210, 0.2))}.property-field--checkbox{flex-direction:column}.property-field--checkbox label{flex-direction:row;align-items:center;gap:var(--le-space-sm, 8px);cursor:pointer}.property-field--checkbox input[type=\"checkbox\"]{width:16px;height:16px;margin:0;cursor:pointer;accent-color:var(--le-color-primary, #1976d2)}.property-field--checkbox .property-hint{margin-left:24px}.no-properties{margin:0;padding:var(--le-space-sm, 8px);font-size:var(--le-font-size-sm, 13px);color:var(--le-color-text-secondary, #666);text-align:center}.property-editor-container{display:flex;flex-direction:column;gap:var(--le-space-md, 12px)}.property-editor-actions{padding-top:var(--le-space-sm, 8px);border-top:1px solid var(--le-color-border, #e5e5e5)}.delete-component-btn{display:flex;align-items:center;justify-content:center;gap:var(--le-space-xs, 4px);width:100%;padding:var(--le-space-sm, 8px) var(--le-space-md, 12px);border:1px solid var(--le-color-danger, #e53935);border-radius:var(--le-radius-md, 6px);background:transparent;color:var(--le-color-danger, #e53935);font-size:var(--le-font-size-sm, 13px);font-weight:500;cursor:pointer;transition:background-color 0.15s, color 0.15s}.delete-component-btn:hover{background:var(--le-color-danger, #e53935);color:white}.delete-component-btn:active{opacity:0.9}";
|
|
144
|
-
|
|
145
|
-
const LeComponent = class {
|
|
146
|
-
constructor(hostRef) {
|
|
147
|
-
registerInstance(this, hostRef);
|
|
148
|
-
}
|
|
149
|
-
get el() { return getElement(this); }
|
|
192
|
+
allowedComponents;
|
|
150
193
|
/**
|
|
151
|
-
*
|
|
152
|
-
* Used to look up property metadata and display the component name.
|
|
194
|
+
* Whether multiple components can be dropped in this slot.
|
|
153
195
|
*/
|
|
154
|
-
|
|
196
|
+
multiple = true;
|
|
155
197
|
/**
|
|
156
|
-
*
|
|
157
|
-
* If not provided, the tag name will be formatted as the display name.
|
|
198
|
+
* Whether this slot is required to have content.
|
|
158
199
|
*/
|
|
159
|
-
|
|
200
|
+
required = false;
|
|
160
201
|
/**
|
|
161
|
-
*
|
|
162
|
-
* Allows parent components to pass their styling classes.
|
|
202
|
+
* Placeholder text for text/textarea inputs in admin mode.
|
|
163
203
|
*/
|
|
164
|
-
|
|
204
|
+
placeholder;
|
|
165
205
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
206
|
+
* The HTML tag to create when there's no slotted element.
|
|
207
|
+
* Used with type="text" or type="textarea" to auto-create elements.
|
|
208
|
+
*
|
|
209
|
+
* @example "h3" - creates <h3 slot="header">content</h3>
|
|
210
|
+
* @example "p" - creates <p slot="content">content</p>
|
|
168
211
|
*/
|
|
169
|
-
|
|
212
|
+
tag;
|
|
170
213
|
/**
|
|
171
|
-
*
|
|
214
|
+
* CSS styles for the slot dropzone container.
|
|
215
|
+
* Useful for layouts - e.g., "flex-direction: row" for horizontal stacks.
|
|
216
|
+
* Only applies in admin mode for type="slot".
|
|
172
217
|
*/
|
|
173
|
-
|
|
218
|
+
slotStyle;
|
|
174
219
|
/**
|
|
175
220
|
* Internal state to track admin mode
|
|
176
221
|
*/
|
|
177
222
|
adminMode = false;
|
|
178
223
|
/**
|
|
179
|
-
*
|
|
224
|
+
* Internal state for text input value (synced from slot content)
|
|
180
225
|
*/
|
|
181
|
-
|
|
226
|
+
textValue = '';
|
|
182
227
|
/**
|
|
183
|
-
*
|
|
228
|
+
* Whether the current textValue contains valid HTML
|
|
184
229
|
*/
|
|
185
|
-
|
|
230
|
+
isValidHtml = true;
|
|
231
|
+
/**
|
|
232
|
+
* Available components loaded from Custom Elements Manifest
|
|
233
|
+
*/
|
|
234
|
+
availableComponents = [];
|
|
235
|
+
/**
|
|
236
|
+
* Whether the component picker popover is open
|
|
237
|
+
*/
|
|
238
|
+
pickerOpen = false;
|
|
239
|
+
/**
|
|
240
|
+
* Reference to the slot element to access assignedNodes
|
|
241
|
+
*/
|
|
242
|
+
slotRef;
|
|
243
|
+
/**
|
|
244
|
+
* The original slotted element (e.g., <h3 slot="header">)
|
|
245
|
+
*/
|
|
246
|
+
slottedElement;
|
|
247
|
+
/**
|
|
248
|
+
* Emitted when text content changes in admin mode.
|
|
249
|
+
* The event detail contains the new text value and validity.
|
|
250
|
+
*/
|
|
251
|
+
leSlotChange;
|
|
186
252
|
disconnectModeObserver;
|
|
187
253
|
connectedCallback() {
|
|
188
|
-
// Find the host element - le-component is rendered inside the component's shadow DOM,
|
|
189
|
-
// so we need to find the shadow root's host element
|
|
190
|
-
this.findHostElement();
|
|
191
254
|
this.disconnectModeObserver = observeModeChanges(this.el, mode => {
|
|
255
|
+
const wasAdmin = this.adminMode;
|
|
192
256
|
this.adminMode = mode === 'admin';
|
|
193
|
-
//
|
|
194
|
-
if (this.adminMode) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
this.
|
|
257
|
+
// When entering admin mode, read content from slotted elements
|
|
258
|
+
if (this.adminMode && !wasAdmin) {
|
|
259
|
+
// Need to wait for render to access slot ref
|
|
260
|
+
requestAnimationFrame(() => this.readSlottedContent());
|
|
261
|
+
// Load available components for the component picker
|
|
262
|
+
if (this.type === 'slot') {
|
|
263
|
+
this.loadAvailableComponents();
|
|
200
264
|
}
|
|
201
265
|
}
|
|
202
266
|
});
|
|
203
267
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Find the host element by traversing up through shadow DOM
|
|
206
|
-
*/
|
|
207
|
-
findHostElement() {
|
|
208
|
-
// Get the shadow root that contains this le-component
|
|
209
|
-
const rootNode = this.el.getRootNode();
|
|
210
|
-
if (rootNode instanceof ShadowRoot) {
|
|
211
|
-
// The host of this shadow root is our target component (e.g., le-card)
|
|
212
|
-
this.hostElement = rootNode.host;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
componentDidLoad() {
|
|
216
|
-
// Read initial property values from the host element
|
|
217
|
-
this.readPropertyValues();
|
|
218
|
-
}
|
|
219
268
|
disconnectedCallback() {
|
|
220
269
|
this.disconnectModeObserver?.();
|
|
221
270
|
}
|
|
222
271
|
/**
|
|
223
|
-
*
|
|
224
|
-
* e.g., 'le-card' -> 'Card'
|
|
272
|
+
* Flag to prevent re-reading content right after we updated it
|
|
225
273
|
*/
|
|
226
|
-
|
|
227
|
-
return tagName
|
|
228
|
-
.replace(/^le-/, '') // Remove 'le-' prefix
|
|
229
|
-
.split('-')
|
|
230
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
231
|
-
.join(' ');
|
|
232
|
-
}
|
|
274
|
+
isUpdating = false;
|
|
233
275
|
/**
|
|
234
|
-
*
|
|
276
|
+
* Read content from slotted elements via assignedNodes()
|
|
235
277
|
*/
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
readSlottedContent() {
|
|
279
|
+
if (!this.slotRef)
|
|
280
|
+
return;
|
|
281
|
+
// Skip if we just updated the content ourselves
|
|
282
|
+
if (this.isUpdating) {
|
|
283
|
+
this.isUpdating = false;
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const assignedNodes = this.slotRef.assignedNodes({ flatten: true });
|
|
287
|
+
// For text/textarea types, we want to edit the innerHTML of slotted elements
|
|
288
|
+
if (this.type === 'text' || this.type === 'textarea') {
|
|
289
|
+
// Find the first element node (skip text nodes that are just whitespace)
|
|
290
|
+
const elementNode = assignedNodes.find(node => node.nodeType === Node.ELEMENT_NODE);
|
|
291
|
+
if (elementNode) {
|
|
292
|
+
// Only update textValue if slotted element changed or we don't have one yet
|
|
293
|
+
if (this.slottedElement !== elementNode) {
|
|
294
|
+
this.slottedElement = elementNode;
|
|
295
|
+
this.textValue = elementNode.innerHTML?.trim() || '';
|
|
296
|
+
// console.log(`[le-slot "${this.name}"] Read slotted content:`, this.textValue);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
// No element, check for direct text content
|
|
301
|
+
const textContent = assignedNodes
|
|
302
|
+
.filter(node => node.nodeType === Node.TEXT_NODE)
|
|
303
|
+
.map(node => node.textContent)
|
|
304
|
+
.join('')
|
|
305
|
+
.trim();
|
|
306
|
+
if (textContent && !this.textValue) {
|
|
307
|
+
this.textValue = textContent;
|
|
308
|
+
// console.log(`[le-slot "${this.name}"] Read text content:`, this.textValue);
|
|
260
309
|
}
|
|
261
310
|
}
|
|
262
|
-
// console.warn(`[le-component] No metadata found for component: ${this.component}`);
|
|
263
|
-
}
|
|
264
|
-
catch (error) {
|
|
265
|
-
// console.warn(`[le-component] Failed to load metadata for component: ${this.component}`, error);
|
|
266
311
|
}
|
|
267
312
|
}
|
|
268
313
|
/**
|
|
269
|
-
*
|
|
314
|
+
* Validates if a string contains valid HTML
|
|
270
315
|
*/
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
316
|
+
validateHtml(html) {
|
|
317
|
+
// Empty string is valid
|
|
318
|
+
if (!html.trim())
|
|
319
|
+
return true;
|
|
320
|
+
// Create a template element to parse the HTML
|
|
321
|
+
const template = document.createElement('template');
|
|
322
|
+
template.innerHTML = html;
|
|
323
|
+
// Check that we don't have obviously broken HTML
|
|
324
|
+
// Count opening and closing tags for common elements
|
|
325
|
+
const openTags = (html.match(/<[a-z][^>]*(?<!\/)>/gi) || []).length;
|
|
326
|
+
const closeTags = (html.match(/<\/[a-z][^>]*>/gi) || []).length;
|
|
327
|
+
const selfClosing = (html.match(/<[a-z][^>]*\/>/gi) || []).length;
|
|
328
|
+
// Simple validation: opening tags (minus self-closing) should roughly match closing tags
|
|
329
|
+
// Allow some tolerance for void elements like <br>, <img>, etc.
|
|
330
|
+
const voidElements = (html.match(/<(br|hr|img|input|meta|link|area|base|col|embed|param|source|track|wbr)[^>]*>/gi) || []).length;
|
|
331
|
+
const effectiveOpenTags = openTags - selfClosing - voidElements;
|
|
332
|
+
// If difference is too large, HTML is likely broken
|
|
333
|
+
if (Math.abs(effectiveOpenTags - closeTags) > 1) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
return true;
|
|
274
337
|
}
|
|
338
|
+
handleTextInput = (event) => {
|
|
339
|
+
const target = event.target;
|
|
340
|
+
this.textValue = target.value;
|
|
341
|
+
this.isValidHtml = this.validateHtml(this.textValue);
|
|
342
|
+
if (this.isValidHtml) {
|
|
343
|
+
// Set flag to prevent slotchange from re-reading what we just wrote
|
|
344
|
+
this.isUpdating = true;
|
|
345
|
+
console.log('Updating text value:', this.textValue, 'slottedElement:', this.slottedElement);
|
|
346
|
+
if (this.slottedElement) {
|
|
347
|
+
// Update existing slotted element's innerHTML
|
|
348
|
+
this.slottedElement.innerHTML = this.textValue;
|
|
349
|
+
}
|
|
350
|
+
else if (this.tag && this.textValue) {
|
|
351
|
+
// No slotted element exists
|
|
352
|
+
// If the slot doesn't have a name, then it's the default slot
|
|
353
|
+
// remove the existing non-slotted content (text nodes and elements without slot attribute)
|
|
354
|
+
const rootNode = this.el.getRootNode();
|
|
355
|
+
if (!this.name && rootNode instanceof ShadowRoot) {
|
|
356
|
+
const hostComponent = rootNode.host;
|
|
357
|
+
Array.from(hostComponent.childNodes).forEach(node => {
|
|
358
|
+
if (node.nodeType === Node.TEXT_NODE || (node.nodeType === Node.ELEMENT_NODE && !node.hasAttribute('slot'))) {
|
|
359
|
+
node.remove();
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
// create one using the specified tag
|
|
364
|
+
this.createSlottedElement();
|
|
365
|
+
}
|
|
366
|
+
else if (this.textValue) {
|
|
367
|
+
// no tag specified - just replace everything in the host component
|
|
368
|
+
const rootNode = this.el.getRootNode();
|
|
369
|
+
if (rootNode instanceof ShadowRoot) {
|
|
370
|
+
const hostComponent = rootNode.host;
|
|
371
|
+
hostComponent.innerHTML = this.textValue;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
this.leSlotChange.emit({
|
|
376
|
+
name: this.name,
|
|
377
|
+
value: this.textValue,
|
|
378
|
+
isValid: this.isValidHtml,
|
|
379
|
+
});
|
|
380
|
+
};
|
|
275
381
|
/**
|
|
276
|
-
*
|
|
382
|
+
* Create a new slotted element when none exists.
|
|
383
|
+
* The element is appended to the host component's light DOM.
|
|
277
384
|
*/
|
|
278
|
-
|
|
279
|
-
if (!this.
|
|
385
|
+
createSlottedElement() {
|
|
386
|
+
if (!this.tag)
|
|
280
387
|
return;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
388
|
+
// Find the host component (le-card, etc.) by traversing up through shadow DOM
|
|
389
|
+
// le-slot is inside le-card's shadow DOM, so we need to find le-card's host
|
|
390
|
+
const rootNode = this.el.getRootNode();
|
|
391
|
+
if (!(rootNode instanceof ShadowRoot))
|
|
392
|
+
return;
|
|
393
|
+
const hostComponent = rootNode.host;
|
|
394
|
+
if (!hostComponent)
|
|
395
|
+
return;
|
|
396
|
+
// Create the new element
|
|
397
|
+
const newElement = document.createElement(this.tag);
|
|
398
|
+
newElement.innerHTML = this.textValue;
|
|
399
|
+
// Set the slot attribute if this is a named slot
|
|
400
|
+
if (this.name) {
|
|
401
|
+
newElement.setAttribute('slot', this.name);
|
|
285
402
|
}
|
|
286
|
-
|
|
403
|
+
// Append to the host component's light DOM
|
|
404
|
+
hostComponent.appendChild(newElement);
|
|
405
|
+
// Store reference to the new element
|
|
406
|
+
this.slottedElement = newElement;
|
|
407
|
+
// console.log(`[le-slot "${this.name}"] Created new <${this.tag}> element`);
|
|
287
408
|
}
|
|
288
409
|
/**
|
|
289
|
-
*
|
|
410
|
+
* Load available components from Custom Elements Manifest
|
|
290
411
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
412
|
+
async loadAvailableComponents() {
|
|
413
|
+
try {
|
|
414
|
+
const { manifestFile } = getLeKitConfig();
|
|
415
|
+
const manifestFileResolved = getAssetPath(`./assets/${manifestFile}`);
|
|
416
|
+
const response = await fetch(manifestFileResolved);
|
|
417
|
+
const manifest = await response.json();
|
|
418
|
+
const components = [];
|
|
419
|
+
const allowedList = this.allowedComponents?.split(',').map(s => s.trim()) || [];
|
|
420
|
+
for (const module of manifest.modules) {
|
|
421
|
+
for (const declaration of module.declarations || []) {
|
|
422
|
+
if (declaration.tagName && declaration.customElement) {
|
|
423
|
+
// Skip internal components (le-slot, le-component, le-popover)
|
|
424
|
+
const isInternal = ['le-slot', 'le-component', 'le-popover'].includes(declaration.tagName);
|
|
425
|
+
if (isInternal)
|
|
426
|
+
continue;
|
|
427
|
+
// If allowedComponents is specified, filter by it
|
|
428
|
+
if (allowedList.length > 0 && !allowedList.includes(declaration.tagName)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
components.push({
|
|
432
|
+
tagName: declaration.tagName,
|
|
433
|
+
name: this.formatComponentName(declaration.tagName),
|
|
434
|
+
description: declaration.description || '',
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
this.availableComponents = components || [];
|
|
296
440
|
}
|
|
297
|
-
|
|
298
|
-
|
|
441
|
+
catch (error) {
|
|
442
|
+
console.warn('[le-slot] Failed to load component manifest:', error);
|
|
299
443
|
}
|
|
300
|
-
return value;
|
|
301
444
|
}
|
|
302
445
|
/**
|
|
303
|
-
*
|
|
446
|
+
* Format a tag name into a display name
|
|
447
|
+
* e.g., 'le-card' -> 'Card'
|
|
304
448
|
*/
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.hostElement.setAttribute(attrName, '');
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
this.hostElement.removeAttribute(attrName);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
else if (value === undefined || value === '') {
|
|
318
|
-
this.hostElement.removeAttribute(attrName);
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
this.hostElement.setAttribute(attrName, String(value));
|
|
322
|
-
}
|
|
323
|
-
// Update local state
|
|
324
|
-
this.propertyValues = { ...this.propertyValues, [attrName]: value };
|
|
449
|
+
formatComponentName(tagName) {
|
|
450
|
+
return tagName
|
|
451
|
+
.replace(/^le-/, '')
|
|
452
|
+
.split('-')
|
|
453
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
454
|
+
.join(' ');
|
|
325
455
|
}
|
|
326
456
|
/**
|
|
327
|
-
*
|
|
457
|
+
* Add a new component to the slot
|
|
328
458
|
*/
|
|
329
|
-
|
|
330
|
-
|
|
459
|
+
addComponent(tagName) {
|
|
460
|
+
// Find the host component by traversing up through shadow DOM
|
|
461
|
+
const rootNode = this.el.getRootNode();
|
|
462
|
+
if (!(rootNode instanceof ShadowRoot))
|
|
331
463
|
return;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (!confirm(`Delete this ${name}?`))
|
|
464
|
+
const hostComponent = rootNode.host;
|
|
465
|
+
if (!hostComponent)
|
|
335
466
|
return;
|
|
336
|
-
//
|
|
337
|
-
const
|
|
338
|
-
if
|
|
339
|
-
|
|
467
|
+
// Create the new component element
|
|
468
|
+
const newElement = document.createElement(tagName);
|
|
469
|
+
// Set the slot attribute if this is a named slot
|
|
470
|
+
if (this.name) {
|
|
471
|
+
newElement.setAttribute('slot', this.name);
|
|
340
472
|
}
|
|
473
|
+
// Append to the host component's light DOM
|
|
474
|
+
hostComponent.appendChild(newElement);
|
|
475
|
+
// Emit change event so the page can save
|
|
476
|
+
this.leSlotChange.emit({
|
|
477
|
+
name: this.name,
|
|
478
|
+
value: hostComponent.innerHTML,
|
|
479
|
+
isValid: true,
|
|
480
|
+
});
|
|
341
481
|
}
|
|
342
482
|
/**
|
|
343
|
-
*
|
|
344
|
-
*/
|
|
345
|
-
renderPropertyEditor() {
|
|
346
|
-
const hasProperties = this.componentMeta && this.componentMeta.attributes.length > 0;
|
|
347
|
-
return (h("div", { class: "property-editor-container" }, hasProperties ? (h("form", { class: "property-editor", onSubmit: e => e.preventDefault() }, this.componentMeta.attributes.map(attr => this.renderPropertyField(attr)))) : (h("p", { class: "no-properties" }, "No editable properties")), h("div", { class: "property-editor-actions" }, h("le-button", { type: "button", variant: "outlined", color: "danger", "full-width": true, onClick: () => this.deleteComponent() }, h("span", { slot: "icon-start" }, "\uD83D\uDDD1\uFE0F"), h("span", null, "Delete Component")))));
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Render a single property field based on its type
|
|
483
|
+
* Handle slot change event to re-read content when nodes are assigned
|
|
351
484
|
*/
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
// Check if type is a union of string literals (e.g., "'default' | 'outlined' | 'elevated'")
|
|
356
|
-
const enumMatch = type.match(/^'[^']+'/);
|
|
357
|
-
if (enumMatch) {
|
|
358
|
-
const options = type.split('|').map(opt => opt.trim().replace(/'/g, ''));
|
|
359
|
-
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))))));
|
|
360
|
-
}
|
|
361
|
-
// Boolean type
|
|
362
|
-
if (type === 'boolean') {
|
|
363
|
-
return (h("div", { class: "property-field property-field--checkbox" }, h("le-checkbox", { name: `prop-${attr.name}`, checked: value === true || value === '', onChange: e => this.handlePropertyChange(attr.name, e.target.checked, type) }, attr.name, attr.description && h("div", { slot: "description" }, attr.description))));
|
|
364
|
-
}
|
|
365
|
-
// Number type
|
|
366
|
-
if (type === 'number') {
|
|
367
|
-
return (h("div", { class: "property-field" }, h("label", { htmlFor: `prop-${attr.name}` }, attr.name, attr.description && h("span", { class: "property-hint" }, attr.description)), h("input", { type: "number", id: `prop-${attr.name}`, value: value ?? '', placeholder: attr.default, onChange: e => this.handlePropertyChange(attr.name, e.target.value, type) })));
|
|
368
|
-
}
|
|
369
|
-
// Default: string/text input
|
|
370
|
-
return (h("div", { class: "property-field" }, h("le-string-input", { name: `prop-${attr.name}`, label: attr.name, value: value ?? '', placeholder: attr.default?.replace(/'/g, ''), onChange: (e) => this.handlePropertyChange(attr.name, e.detail.value, type) }, h("span", { slot: "description" }, attr.description))));
|
|
371
|
-
}
|
|
485
|
+
handleSlotChange = () => {
|
|
486
|
+
this.readSlottedContent();
|
|
487
|
+
};
|
|
372
488
|
render() {
|
|
373
|
-
const
|
|
374
|
-
//
|
|
375
|
-
|
|
376
|
-
|
|
489
|
+
const displayLabel = this.label || this.name;
|
|
490
|
+
// Always render the same structure, CSS handles visibility via .admin-mode class
|
|
491
|
+
return (h(Host, { key: '0ffbcff05009d390a4de52aac1395c4c769ed948', class: {
|
|
492
|
+
'admin-mode': this.adminMode,
|
|
493
|
+
'invalid-html': !this.isValidHtml,
|
|
494
|
+
}, role: this.adminMode ? 'region' : undefined, "aria-label": this.adminMode ? `Slot: ${displayLabel}` : undefined, "data-slot-name": this.name, "data-slot-type": this.type, "data-allowed": this.allowedComponents, "data-multiple": this.multiple, "data-required": this.required }, this.adminMode ? (h("div", { class: "le-slot-container" }, h("div", { class: classnames('le-slot-header', {
|
|
495
|
+
'le-slot-header-no-label': !displayLabel,
|
|
496
|
+
'le-slot-header-text': this.type === 'text',
|
|
497
|
+
'le-slot-header-error': !this.isValidHtml,
|
|
498
|
+
}) }, displayLabel && (h("span", { class: "le-slot-label" }, displayLabel, this.required && h("span", { class: "le-slot-required" }, "*"))), !this.isValidHtml && h("span", { class: "le-slot-invalid" }, "\u26A0 Invalid HTML"), this.type === 'slot' && this.adminMode && (h("le-popover", { mode: "default", showClose: true, align: "start", position: "right", popoverTitle: "Add Component", open: this.pickerOpen, onLePopoverOpen: () => (this.pickerOpen = true), onLePopoverClose: () => (this.pickerOpen = false) }, h("le-button", { type: "button", class: "le-slot-button", slot: "trigger", variant: "clear", size: "small", "aria-label": "Add component", "icon-only": true }, h("span", { class: "le-slot-add-btn", slot: "icon-only" }, "+")), h("div", { class: "le-slot-picker" }, this.availableComponents.length > 0 ? (h("ul", { class: "le-slot-picker-list" }, this.availableComponents.map(component => (h("li", { key: component.tagName }, h("button", { class: "le-slot-picker-item", onClick: () => {
|
|
499
|
+
this.addComponent(component.tagName);
|
|
500
|
+
this.pickerOpen = false;
|
|
501
|
+
} }, h("span", { class: "le-slot-picker-name" }, component.name), component.description && h("span", { class: "le-slot-picker-desc" }, component.description))))))) : (h("div", { class: "le-slot-picker-empty" }, "No components available")))))), this.renderContent())) : (
|
|
502
|
+
// In default mode, just pass through the slot - slotted content renders naturally
|
|
503
|
+
// Note: We use unnamed slot here because named slots from parent component
|
|
504
|
+
// are passed as le-slot's light DOM children
|
|
505
|
+
h("slot", null))));
|
|
506
|
+
}
|
|
507
|
+
renderContent() {
|
|
508
|
+
// Create the slot element with ref for reading assignedNodes
|
|
509
|
+
// Wrap in a hidden div since slot elements can't have style prop in Stencil
|
|
510
|
+
// Note: We use unnamed slot here because named slots from parent component
|
|
511
|
+
// are passed as le-slot's light DOM children
|
|
512
|
+
const slotElement = (h("div", { class: "hidden-slot" }, h("slot", { ref: el => (this.slotRef = el), onSlotchange: this.handleSlotChange })));
|
|
513
|
+
switch (this.type) {
|
|
514
|
+
case 'text':
|
|
515
|
+
return (h("div", { class: { 'le-slot-input': true, 'has-error': !this.isValidHtml } }, h("le-string-input", { mode: "default", value: this.textValue, placeholder: this.placeholder || `Enter ${this.label || this.name || 'text'}...`, onChange: this.handleTextInput }), slotElement));
|
|
516
|
+
case 'textarea':
|
|
517
|
+
return (h("div", { class: { 'le-slot-input': true, 'has-error': !this.isValidHtml } }, h("textarea", { value: this.textValue, placeholder: this.placeholder || `Enter ${this.label || this.name || 'text'}...`, onInput: this.handleTextInput, required: this.required, rows: 3 }), slotElement));
|
|
518
|
+
case 'slot':
|
|
519
|
+
default:
|
|
520
|
+
// Parse slotStyle string into style object if provided
|
|
521
|
+
const dropzoneStyle = {};
|
|
522
|
+
if (this.slotStyle) {
|
|
523
|
+
this.slotStyle.split(';').forEach(rule => {
|
|
524
|
+
const [prop, value] = rule.split(':').map(s => s.trim());
|
|
525
|
+
if (prop && value) {
|
|
526
|
+
// Convert kebab-case to camelCase for style object
|
|
527
|
+
const camelProp = prop.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
528
|
+
dropzoneStyle[camelProp] = value;
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return (h("div", { class: "le-slot-dropzone", style: dropzoneStyle }, h("slot", { ref: el => (this.slotRef = el), onSlotchange: this.handleSlotChange })));
|
|
377
533
|
}
|
|
378
|
-
// In admin mode, show wrapper with header and settings
|
|
379
|
-
return (h(Host, { class: classnames(this.component, this.hostClass, 'admin-mode'), style: this.hostStyle }, h("div", { class: "le-component-wrapper" }, h("div", { class: "le-component-header" }, h("span", { class: "le-component-name" }, name), h("le-popover", { popoverTitle: `${name} Settings`, position: "right", align: "start", "min-width": "300px", mode: "default" }, h("le-button", { type: "button", class: "le-component-button", slot: "trigger", variant: "clear", size: "small", "aria-label": "Edit component properties", "icon-only": true }, h("span", { class: "le-component-trigger", slot: "icon-only" }, "\u2699")), this.renderPropertyEditor())), h("div", { class: "le-component-content" }, h("slot", null)))));
|
|
380
534
|
}
|
|
381
|
-
}
|
|
382
|
-
|
|
535
|
+
static get style() { return leSlotDefaultCss; }
|
|
536
|
+
}, [769, "le-slot", {
|
|
537
|
+
"type": [1],
|
|
538
|
+
"name": [1],
|
|
539
|
+
"label": [1],
|
|
540
|
+
"description": [1],
|
|
541
|
+
"allowedComponents": [1, "allowed-components"],
|
|
542
|
+
"multiple": [4],
|
|
543
|
+
"required": [4],
|
|
544
|
+
"placeholder": [1],
|
|
545
|
+
"tag": [1],
|
|
546
|
+
"slotStyle": [1, "slot-style"],
|
|
547
|
+
"adminMode": [32],
|
|
548
|
+
"textValue": [32],
|
|
549
|
+
"isValidHtml": [32],
|
|
550
|
+
"availableComponents": [32],
|
|
551
|
+
"pickerOpen": [32]
|
|
552
|
+
}]);
|
|
553
|
+
function defineCustomElement$3() {
|
|
554
|
+
if (typeof customElements === "undefined") {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const components = ["le-slot", "le-button", "le-checkbox", "le-component", "le-popover", "le-slot", "le-string-input"];
|
|
558
|
+
components.forEach(tagName => { switch (tagName) {
|
|
559
|
+
case "le-slot":
|
|
560
|
+
if (!customElements.get(tagName)) {
|
|
561
|
+
customElements.define(tagName, LeSlot);
|
|
562
|
+
}
|
|
563
|
+
break;
|
|
564
|
+
case "le-button":
|
|
565
|
+
if (!customElements.get(tagName)) {
|
|
566
|
+
defineCustomElement();
|
|
567
|
+
}
|
|
568
|
+
break;
|
|
569
|
+
case "le-checkbox":
|
|
570
|
+
if (!customElements.get(tagName)) {
|
|
571
|
+
defineCustomElement$1();
|
|
572
|
+
}
|
|
573
|
+
break;
|
|
574
|
+
case "le-component":
|
|
575
|
+
if (!customElements.get(tagName)) {
|
|
576
|
+
defineCustomElement$2();
|
|
577
|
+
}
|
|
578
|
+
break;
|
|
579
|
+
case "le-popover":
|
|
580
|
+
if (!customElements.get(tagName)) {
|
|
581
|
+
defineCustomElement$5();
|
|
582
|
+
}
|
|
583
|
+
break;
|
|
584
|
+
case "le-slot":
|
|
585
|
+
if (!customElements.get(tagName)) {
|
|
586
|
+
defineCustomElement$3();
|
|
587
|
+
}
|
|
588
|
+
break;
|
|
589
|
+
case "le-string-input":
|
|
590
|
+
if (!customElements.get(tagName)) {
|
|
591
|
+
defineCustomElement$4();
|
|
592
|
+
}
|
|
593
|
+
break;
|
|
594
|
+
} });
|
|
595
|
+
}
|
|
383
596
|
|
|
384
|
-
const
|
|
597
|
+
const leComponentCss = ":host{display:contents}:host(.admin-mode){display:block}.le-component-wrapper{position:relative;border:2px dashed var(--le-admin-border-color, #90caf9);border-radius:var(--le-radius-md, 8px);background:var(--le-admin-bg, rgba(144, 202, 249, 0.05));transition:border-color 0.2s ease, box-shadow 0.2s ease}.le-component-wrapper:hover{border-color:var(--le-admin-border-hover, #42a5f5);box-shadow:0 0 0 2px var(--le-admin-glow, rgba(66, 165, 245, 0.2))}.le-component-header{display:flex;align-items:center;justify-content:space-between;gap:var(--le-spacing-1, 4px);padding:0 0 0 var(--le-spacing-1, 4px);background:var(--le-admin-header-bg, rgba(144, 202, 249, 0.15));border-bottom:1px solid var(--le-admin-border-color, #90caf9);border-radius:var(--le-radius-md, 8px) var(--le-radius-md, 8px) 0 0;font-size:var(--le-font-size-xs, 11px)}.le-component-name{font-weight:var(--le-font-weight-medium, 500);color:var(--le-admin-text, #1976d2);text-transform:capitalize;text-align:start;overflow:hidden;width:0;flex:1 1 0%}.le-component-content{padding:var(--le-space-xs, 4px)}.le-component-trigger{font-size:24px;line-height:0px;width:12px;height:12px}.le-component-button{width:20px}.property-editor{display:flex;flex-direction:column;gap:var(--le-space-sm, 8px);max-width:380px}.property-field{display:flex;flex-direction:column;gap:var(--le-space-xs, 4px)}.property-field label{display:flex;flex-direction:column;gap:2px;font-size:var(--le-font-size-sm, 13px);font-weight:var(--le-font-weight-medium, 500);color:var(--le-color-text, #333)}.property-hint{font-size:var(--le-font-size-xs, 11px);font-weight:normal;color:var(--le-color-text-secondary, #666);line-height:1.3}.property-field input[type=\"text\"],.property-field input[type=\"number\"],.property-field select{padding:var(--le-space-xs, 4px) var(--le-space-sm, 8px);border:1px solid var(--le-color-border, #ddd);border-radius:var(--le-radius-md, 7px);font-size:var(--le-font-size-sm, 13px);font-family:inherit;background:var(--le-color-surface, #fff);color:var(--le-color-text, #333);transition:border-color 0.15s ease, box-shadow 0.15s ease}.property-field input:focus,.property-field select:focus{outline:none;border-color:var(--le-color-primary, #1976d2);box-shadow:0 0 0 2px var(--le-color-primary-light, rgba(25, 118, 210, 0.2))}.property-field--checkbox{flex-direction:column}.property-field--checkbox label{flex-direction:row;align-items:center;gap:var(--le-space-sm, 8px);cursor:pointer}.property-field--checkbox input[type=\"checkbox\"]{width:16px;height:16px;margin:0;cursor:pointer;accent-color:var(--le-color-primary, #1976d2)}.property-field--checkbox .property-hint{margin-left:24px}.no-properties{margin:0;padding:var(--le-space-sm, 8px);font-size:var(--le-font-size-sm, 13px);color:var(--le-color-text-secondary, #666);text-align:center}.property-editor-container{display:flex;flex-direction:column;gap:var(--le-space-md, 12px)}.property-editor-actions{padding-top:var(--le-space-sm, 8px);border-top:1px solid var(--le-color-border, #e5e5e5)}.delete-component-btn{display:flex;align-items:center;justify-content:center;gap:var(--le-space-xs, 4px);width:100%;padding:var(--le-space-sm, 8px) var(--le-space-md, 12px);border:1px solid var(--le-color-danger, #e53935);border-radius:var(--le-radius-md, 6px);background:transparent;color:var(--le-color-danger, #e53935);font-size:var(--le-font-size-sm, 13px);font-weight:500;cursor:pointer;transition:background-color 0.15s, color 0.15s}.delete-component-btn:hover{background:var(--le-color-danger, #e53935);color:white}.delete-component-btn:active{opacity:0.9}";
|
|
385
598
|
|
|
386
|
-
const
|
|
387
|
-
constructor(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
599
|
+
const LeComponent = /*@__PURE__*/ proxyCustomElement(class LeComponent extends HTMLElement {
|
|
600
|
+
constructor(registerHost) {
|
|
601
|
+
super();
|
|
602
|
+
if (registerHost !== false) {
|
|
603
|
+
this.__registerHost();
|
|
604
|
+
}
|
|
605
|
+
this.__attachShadow();
|
|
391
606
|
}
|
|
392
|
-
get el() { return
|
|
393
|
-
/**
|
|
394
|
-
* Mode of the popover should be 'default' for internal use
|
|
395
|
-
*/
|
|
396
|
-
mode;
|
|
397
|
-
/**
|
|
398
|
-
* Whether the popover is currently open
|
|
399
|
-
*/
|
|
400
|
-
open = false;
|
|
401
|
-
/**
|
|
402
|
-
* Position of the popover relative to its trigger
|
|
403
|
-
*/
|
|
404
|
-
position = 'bottom';
|
|
405
|
-
/**
|
|
406
|
-
* Alignment of the popover
|
|
407
|
-
*/
|
|
408
|
-
align = 'start';
|
|
607
|
+
get el() { return this; }
|
|
409
608
|
/**
|
|
410
|
-
*
|
|
411
|
-
|
|
412
|
-
popoverTitle;
|
|
413
|
-
/**
|
|
414
|
-
* Whether to show a close button in the header
|
|
609
|
+
* The tag name of the component (e.g., 'le-card').
|
|
610
|
+
* Used to look up property metadata and display the component name.
|
|
415
611
|
*/
|
|
416
|
-
|
|
612
|
+
component;
|
|
417
613
|
/**
|
|
418
|
-
*
|
|
614
|
+
* Optional display name for the component.
|
|
615
|
+
* If not provided, the tag name will be formatted as the display name.
|
|
419
616
|
*/
|
|
420
|
-
|
|
617
|
+
displayName;
|
|
421
618
|
/**
|
|
422
|
-
*
|
|
619
|
+
* Classes to apply to the host element.
|
|
620
|
+
* Allows parent components to pass their styling classes.
|
|
423
621
|
*/
|
|
424
|
-
|
|
622
|
+
hostClass;
|
|
425
623
|
/**
|
|
426
|
-
*
|
|
624
|
+
* Inline styles to apply to the host element.
|
|
625
|
+
* Allows parent components to pass dynamic styles (e.g., flex properties).
|
|
427
626
|
*/
|
|
428
|
-
|
|
627
|
+
hostStyle;
|
|
429
628
|
/**
|
|
430
|
-
*
|
|
629
|
+
* Reference to the host element (found automatically from parent)
|
|
431
630
|
*/
|
|
432
|
-
|
|
631
|
+
hostElement;
|
|
433
632
|
/**
|
|
434
|
-
*
|
|
633
|
+
* Internal state to track admin mode
|
|
435
634
|
*/
|
|
436
|
-
|
|
635
|
+
adminMode = false;
|
|
437
636
|
/**
|
|
438
|
-
*
|
|
637
|
+
* Component metadata loaded from Custom Elements Manifest
|
|
439
638
|
*/
|
|
440
|
-
|
|
639
|
+
componentMeta = null;
|
|
441
640
|
/**
|
|
442
|
-
*
|
|
641
|
+
* Current property values of the host component
|
|
443
642
|
*/
|
|
444
|
-
|
|
643
|
+
propertyValues = {};
|
|
644
|
+
disconnectModeObserver;
|
|
645
|
+
connectedCallback() {
|
|
646
|
+
// Find the host element - le-component is rendered inside the component's shadow DOM,
|
|
647
|
+
// so we need to find the shadow root's host element
|
|
648
|
+
this.findHostElement();
|
|
649
|
+
this.disconnectModeObserver = observeModeChanges(this.el, mode => {
|
|
650
|
+
this.adminMode = mode === 'admin';
|
|
651
|
+
// Load metadata and refresh property values only when entering admin mode
|
|
652
|
+
if (this.adminMode) {
|
|
653
|
+
if (!this.componentMeta) {
|
|
654
|
+
this.loadComponentMetadata();
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
this.readPropertyValues();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
}
|
|
445
662
|
/**
|
|
446
|
-
*
|
|
663
|
+
* Find the host element by traversing up through shadow DOM
|
|
447
664
|
*/
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
665
|
+
findHostElement() {
|
|
666
|
+
// Get the shadow root that contains this le-component
|
|
667
|
+
const rootNode = this.el.getRootNode();
|
|
668
|
+
if (rootNode instanceof ShadowRoot) {
|
|
669
|
+
// The host of this shadow root is our target component (e.g., le-card)
|
|
670
|
+
this.hostElement = rootNode.host;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
454
673
|
componentDidLoad() {
|
|
455
|
-
//
|
|
456
|
-
this.
|
|
457
|
-
// Listen for other popovers opening to close this one
|
|
458
|
-
document.addEventListener('le-popover-will-open', this.handleOtherPopoverOpen);
|
|
674
|
+
// Read initial property values from the host element
|
|
675
|
+
this.readPropertyValues();
|
|
459
676
|
}
|
|
460
677
|
disconnectedCallback() {
|
|
461
|
-
this.
|
|
462
|
-
document.removeEventListener('le-popover-will-open', this.handleOtherPopoverOpen);
|
|
463
|
-
this.removeScrollListeners();
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Find all scrollable parent elements
|
|
467
|
-
*/
|
|
468
|
-
getScrollParents(element) {
|
|
469
|
-
const scrollParents = [];
|
|
470
|
-
let parent = element.parentElement;
|
|
471
|
-
while (parent) {
|
|
472
|
-
const style = getComputedStyle(parent);
|
|
473
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
474
|
-
if (/(auto|scroll)/.test(overflow)) {
|
|
475
|
-
scrollParents.push(parent);
|
|
476
|
-
}
|
|
477
|
-
parent = parent.parentElement;
|
|
478
|
-
}
|
|
479
|
-
// Always include window for page scroll
|
|
480
|
-
return scrollParents;
|
|
678
|
+
this.disconnectModeObserver?.();
|
|
481
679
|
}
|
|
482
680
|
/**
|
|
483
|
-
*
|
|
681
|
+
* Formats a tag name into a display name
|
|
682
|
+
* e.g., 'le-card' -> 'Card'
|
|
484
683
|
*/
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
parent.addEventListener('scroll', this.handleScroll, { passive: true });
|
|
492
|
-
});
|
|
493
|
-
// Also listen to window scroll and resize
|
|
494
|
-
window.addEventListener('scroll', this.handleScroll, { passive: true });
|
|
495
|
-
window.addEventListener('resize', this.handleScroll, { passive: true });
|
|
684
|
+
formatDisplayName(tagName) {
|
|
685
|
+
return tagName
|
|
686
|
+
.replace(/^le-/, '') // Remove 'le-' prefix
|
|
687
|
+
.split('-')
|
|
688
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
689
|
+
.join(' ');
|
|
496
690
|
}
|
|
497
691
|
/**
|
|
498
|
-
*
|
|
692
|
+
* Load component metadata from the Custom Elements Manifest
|
|
499
693
|
*/
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
this.
|
|
694
|
+
async loadComponentMetadata() {
|
|
695
|
+
try {
|
|
696
|
+
// Fetch the manifest from configured URL
|
|
697
|
+
const { manifestFile } = getLeKitConfig();
|
|
698
|
+
const manifestFileResolved = getAssetPath(`./assets/${manifestFile}`);
|
|
699
|
+
const response = await fetch(manifestFileResolved);
|
|
700
|
+
const manifest = await response.json();
|
|
701
|
+
// Find the component definition
|
|
702
|
+
for (const module of manifest.modules) {
|
|
703
|
+
for (const declaration of module.declarations || []) {
|
|
704
|
+
if (declaration.tagName === this.component) {
|
|
705
|
+
const attributes = (declaration.attributes || []).filter((attr) => !this.isInternalAttribute(attr.name));
|
|
706
|
+
this.componentMeta = {
|
|
707
|
+
tagName: declaration.tagName,
|
|
708
|
+
description: declaration.description,
|
|
709
|
+
attributes,
|
|
710
|
+
};
|
|
711
|
+
// console.log(`[le-component] Loaded metadata for ${this.component}:`, this.componentMeta);
|
|
712
|
+
// Read property values after metadata is loaded
|
|
713
|
+
this.readPropertyValues();
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
// console.warn(`[le-component] No metadata found for component: ${this.component}`);
|
|
525
719
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const customEvent = event;
|
|
529
|
-
if (customEvent.detail?.popover === this.el)
|
|
530
|
-
return;
|
|
531
|
-
if (this.open) {
|
|
532
|
-
this.hide();
|
|
720
|
+
catch (error) {
|
|
721
|
+
// console.warn(`[le-component] Failed to load metadata for component: ${this.component}`, error);
|
|
533
722
|
}
|
|
534
|
-
}
|
|
723
|
+
}
|
|
535
724
|
/**
|
|
536
|
-
*
|
|
725
|
+
* Check if an attribute is internal (should not be shown in editor)
|
|
537
726
|
*/
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
}));
|
|
542
|
-
this.popoverEl?.showPopover();
|
|
727
|
+
isInternalAttribute(name) {
|
|
728
|
+
const internalAttrs = ['mode', 'theme', 'class', 'style', 'id', 'slot'];
|
|
729
|
+
return internalAttrs.includes(name);
|
|
543
730
|
}
|
|
544
731
|
/**
|
|
545
|
-
*
|
|
732
|
+
* Read current property values from the host element
|
|
546
733
|
*/
|
|
547
|
-
|
|
548
|
-
this.
|
|
734
|
+
readPropertyValues() {
|
|
735
|
+
if (!this.hostElement || !this.componentMeta)
|
|
736
|
+
return;
|
|
737
|
+
const values = {};
|
|
738
|
+
for (const attr of this.componentMeta.attributes) {
|
|
739
|
+
const value = this.hostElement.getAttribute(attr.name);
|
|
740
|
+
values[attr.name] = this.parseAttributeValue(value, attr.type?.text);
|
|
741
|
+
}
|
|
742
|
+
this.propertyValues = values;
|
|
549
743
|
}
|
|
550
744
|
/**
|
|
551
|
-
*
|
|
745
|
+
* Parse an attribute value based on its type
|
|
552
746
|
*/
|
|
553
|
-
|
|
554
|
-
if (
|
|
555
|
-
|
|
747
|
+
parseAttributeValue(value, type) {
|
|
748
|
+
if (value === null)
|
|
749
|
+
return undefined;
|
|
750
|
+
if (type === 'boolean') {
|
|
751
|
+
return value !== null && value !== 'false';
|
|
556
752
|
}
|
|
557
|
-
|
|
558
|
-
|
|
753
|
+
if (type === 'number') {
|
|
754
|
+
return parseFloat(value);
|
|
559
755
|
}
|
|
756
|
+
return value;
|
|
560
757
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (!this.triggerEl || !this.popoverEl)
|
|
758
|
+
/**
|
|
759
|
+
* Handle property value changes from the editor
|
|
760
|
+
*/
|
|
761
|
+
handlePropertyChange(attrName, value, type) {
|
|
762
|
+
if (!this.hostElement)
|
|
567
763
|
return;
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
const viewportPadding = 8;
|
|
573
|
-
let position = this.position;
|
|
574
|
-
let align = this.align;
|
|
575
|
-
// Auto-position logic
|
|
576
|
-
const spaceBelow = viewportHeight - triggerRect.bottom - viewportPadding;
|
|
577
|
-
const spaceAbove = triggerRect.top - viewportPadding;
|
|
578
|
-
const spaceRight = viewportWidth - triggerRect.right - viewportPadding;
|
|
579
|
-
const spaceLeft = triggerRect.left - viewportPadding;
|
|
580
|
-
if (position === 'auto') {
|
|
581
|
-
if (spaceBelow >= popoverRect.height + this.offset) {
|
|
582
|
-
position = 'bottom';
|
|
583
|
-
}
|
|
584
|
-
else if (spaceAbove >= popoverRect.height + this.offset) {
|
|
585
|
-
position = 'top';
|
|
586
|
-
}
|
|
587
|
-
else if (spaceRight >= popoverRect.width + this.offset) {
|
|
588
|
-
position = 'right';
|
|
589
|
-
}
|
|
590
|
-
else if (spaceLeft >= popoverRect.width + this.offset) {
|
|
591
|
-
position = 'left';
|
|
764
|
+
// Update the host element's attribute
|
|
765
|
+
if (type === 'boolean') {
|
|
766
|
+
if (value) {
|
|
767
|
+
this.hostElement.setAttribute(attrName, '');
|
|
592
768
|
}
|
|
593
769
|
else {
|
|
594
|
-
|
|
595
|
-
if (maxSpace === spaceBelow)
|
|
596
|
-
position = 'bottom';
|
|
597
|
-
else if (maxSpace === spaceAbove)
|
|
598
|
-
position = 'top';
|
|
599
|
-
else if (maxSpace === spaceRight)
|
|
600
|
-
position = 'right';
|
|
601
|
-
else
|
|
602
|
-
position = 'left';
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
// Adjust alignment for horizontal overflow
|
|
606
|
-
if (position === 'top' || position === 'bottom') {
|
|
607
|
-
if (align === 'start' && triggerRect.left + popoverRect.width > viewportWidth - viewportPadding) {
|
|
608
|
-
align = 'end';
|
|
609
|
-
}
|
|
610
|
-
else if (align === 'end' && triggerRect.right - popoverRect.width < viewportPadding) {
|
|
611
|
-
align = 'start';
|
|
612
|
-
}
|
|
613
|
-
else if (align === 'center') {
|
|
614
|
-
const triggerCenter = triggerRect.left + triggerRect.width / 2;
|
|
615
|
-
if (triggerCenter - popoverRect.width / 2 < viewportPadding) {
|
|
616
|
-
align = 'start';
|
|
617
|
-
}
|
|
618
|
-
else if (triggerCenter + popoverRect.width / 2 > viewportWidth - viewportPadding) {
|
|
619
|
-
align = 'end';
|
|
620
|
-
}
|
|
770
|
+
this.hostElement.removeAttribute(attrName);
|
|
621
771
|
}
|
|
622
772
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
let left = 0;
|
|
626
|
-
let maxHeight = null;
|
|
627
|
-
switch (position) {
|
|
628
|
-
case 'top':
|
|
629
|
-
top = triggerRect.top - popoverRect.height - this.offset;
|
|
630
|
-
if (top < viewportPadding) {
|
|
631
|
-
maxHeight = triggerRect.top - this.offset - viewportPadding * 2;
|
|
632
|
-
top = viewportPadding;
|
|
633
|
-
}
|
|
634
|
-
break;
|
|
635
|
-
case 'bottom':
|
|
636
|
-
top = triggerRect.bottom + this.offset;
|
|
637
|
-
if (top + popoverRect.height > viewportHeight - viewportPadding) {
|
|
638
|
-
maxHeight = viewportHeight - top - viewportPadding;
|
|
639
|
-
}
|
|
640
|
-
break;
|
|
641
|
-
case 'left':
|
|
642
|
-
left = triggerRect.left - popoverRect.width - this.offset;
|
|
643
|
-
top = triggerRect.top;
|
|
644
|
-
if (left < viewportPadding)
|
|
645
|
-
left = viewportPadding;
|
|
646
|
-
break;
|
|
647
|
-
case 'right':
|
|
648
|
-
left = triggerRect.right + this.offset;
|
|
649
|
-
top = triggerRect.top;
|
|
650
|
-
if (left + popoverRect.width > viewportWidth - viewportPadding) {
|
|
651
|
-
left = viewportWidth - popoverRect.width - viewportPadding;
|
|
652
|
-
}
|
|
653
|
-
break;
|
|
654
|
-
}
|
|
655
|
-
// Calculate horizontal alignment for top/bottom
|
|
656
|
-
if (position === 'top' || position === 'bottom') {
|
|
657
|
-
switch (align) {
|
|
658
|
-
case 'start':
|
|
659
|
-
left = triggerRect.left;
|
|
660
|
-
break;
|
|
661
|
-
case 'center':
|
|
662
|
-
left = triggerRect.left + triggerRect.width / 2 - popoverRect.width / 2;
|
|
663
|
-
break;
|
|
664
|
-
case 'end':
|
|
665
|
-
left = triggerRect.right - popoverRect.width;
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
// Constrain to viewport
|
|
669
|
-
if (left < viewportPadding) {
|
|
670
|
-
left = viewportPadding;
|
|
671
|
-
}
|
|
672
|
-
else if (left + popoverRect.width > viewportWidth - viewportPadding) {
|
|
673
|
-
left = viewportWidth - popoverRect.width - viewportPadding;
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
// Calculate vertical alignment for left/right
|
|
677
|
-
if (position === 'left' || position === 'right') {
|
|
678
|
-
switch (align) {
|
|
679
|
-
case 'start':
|
|
680
|
-
top = triggerRect.top;
|
|
681
|
-
break;
|
|
682
|
-
case 'center':
|
|
683
|
-
top = triggerRect.top + triggerRect.height / 2 - popoverRect.height / 2;
|
|
684
|
-
break;
|
|
685
|
-
case 'end':
|
|
686
|
-
top = triggerRect.bottom - popoverRect.height;
|
|
687
|
-
break;
|
|
688
|
-
}
|
|
689
|
-
if (top < viewportPadding)
|
|
690
|
-
top = viewportPadding;
|
|
691
|
-
if (top + popoverRect.height > viewportHeight - viewportPadding) {
|
|
692
|
-
maxHeight = viewportHeight - top - viewportPadding;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
// Apply styles
|
|
696
|
-
this.popoverEl.style.top = `${top}px`;
|
|
697
|
-
this.popoverEl.style.left = `${left}px`;
|
|
698
|
-
if (maxHeight !== null && maxHeight > 100) {
|
|
699
|
-
this.popoverEl.style.maxHeight = `${maxHeight}px`;
|
|
700
|
-
this.popoverEl.style.overflowY = 'auto';
|
|
773
|
+
else if (value === undefined || value === '') {
|
|
774
|
+
this.hostElement.removeAttribute(attrName);
|
|
701
775
|
}
|
|
702
776
|
else {
|
|
703
|
-
this.
|
|
704
|
-
this.popoverEl.style.overflowY = '';
|
|
777
|
+
this.hostElement.setAttribute(attrName, String(value));
|
|
705
778
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
render() {
|
|
709
|
-
const popoverStyles = {
|
|
710
|
-
visibility: this.isPositioned ? 'visible' : 'hidden',
|
|
711
|
-
};
|
|
712
|
-
if (this.width)
|
|
713
|
-
popoverStyles.width = this.width;
|
|
714
|
-
if (this.minWidth)
|
|
715
|
-
popoverStyles.minWidth = this.minWidth;
|
|
716
|
-
if (this.maxWidth)
|
|
717
|
-
popoverStyles.maxWidth = this.maxWidth;
|
|
718
|
-
return [
|
|
719
|
-
h("div", { key: '3d2a3b86ddb3be577bd0e976a5a00f25396a97fb', class: "le-popover-trigger", ref: (el) => (this.triggerEl = el), onClick: this.handleTriggerClick }, h("slot", { key: '9db2e9e2b0bdb25c5a2361115d2094292fe692ec', name: "trigger" }, h("button", { key: '88d78b192f72731f00d6131b92b8d6a4b445d7f9', type: "button", class: "le-popover-default-trigger" }, h("span", { key: '0f2913f160cda5dcbeb20c714219d587196e230b' }, "\u2295")))),
|
|
720
|
-
h("div", { key: 'b65d2de900ff6e67a62d92d7452db34afde9f257', id: this.uniqueId, class: "le-popover-content", popover: this.closeOnClickOutside ? 'auto' : 'manual', ref: (el) => (this.popoverEl = el), style: popoverStyles }, (this.popoverTitle || this.showClose) && (h("div", { key: '323061fc49c8e0fc9ae541dfc576e551b0a83818', class: "le-popover-header" }, this.popoverTitle && h("span", { key: 'b1d9f4203966ae6a0bb14186824596643954d6f8', class: "le-popover-title" }, this.popoverTitle), this.showClose && (h("button", { key: 'd0d335d8c9897ed9ba7bd0370572a8cafa72b044', type: "button", class: "le-popover-close", onClick: () => this.hide(), "aria-label": "Close" }, "\u00D7")))), h("div", { key: '52d3294394b0e1fd49f8c361414e228feed68ea9', class: "le-popover-body" }, h("slot", { key: '16d8691545f2eaa44f136bfea33a1f1d71d18cd7' })))
|
|
721
|
-
];
|
|
722
|
-
}
|
|
723
|
-
};
|
|
724
|
-
LePopover.style = lePopoverCss;
|
|
725
|
-
|
|
726
|
-
const leSlotDefaultCss = ":host{display:contents;--le-slot-border-color:#0088ff;--le-slot-bg-color:rgba(0, 136, 255, 0.05);--le-slot-header-bg:rgb(218, 238, 255);--le-slot-label-color:#0066cc;--le-slot-description-color:#666;--le-slot-required-color:#e53935;--le-slot-dropzone-min-height:20px;--le-slot-dropzone-border-color:#ccc}.le-slot-container,.le-slot-header,.le-slot-description,.le-slot-dropzone,.le-slot-input{display:none}.hidden-slot{display:none}:host(.admin-mode){display:block;flex:1}:host(.admin-mode) .le-slot-container{position:relative;display:flex;flex-direction:column;border:2px dashed var(--le-slot-border-color);border-radius:4px;background:var(--le-slot-bg-color);margin:4px 0}:host(.admin-mode) .le-slot-header{display:flex;align-items:center;gap:4px;padding:0 0 0 var(--le-spacing-1, 4px);background:var(--le-slot-header-bg);border-bottom:1px solid var(--le-slot-border-color);font-size:var(--le-font-size-xs, 11px);font-weight:400;text-transform:capitalize}:host(.admin-mode) .le-slot-header-no-label{justify-content:flex-end;height:16px;border:none;background-color:transparent}.le-slot-label{color:var(--le-slot-label-color);text-align:start;overflow:hidden;width:0;flex:1 1 0%}.le-slot-required{color:var(--le-slot-required-color);font-weight:bold}:host(.admin-mode) .le-slot-description{display:block;padding:4px 8px;font-size:12px;color:var(--le-slot-description-color);font-style:italic}:host(.admin-mode) .le-slot-description-icon{display:inline-block;font-size:9px;line-height:1;cursor:pointer;color:var(--le-slot-description-color)}:host(.admin-mode) .le-slot-dropzone{display:block;min-height:var(--le-slot-dropzone-min-height);padding:var(--le-spacing-1, 4px);position:relative}:host(.admin-mode) .le-slot-dropzone:empty::before{content:'Drop content here';display:flex;align-items:center;justify-content:center;position:absolute;inset:8px;border:2px dashed var(--le-slot-dropzone-border-color);border-radius:4px;color:#999;font-size:12px;pointer-events:none}:host(.admin-mode.drag-over) .le-slot-container{border-color:#00cc66;background:rgba(0, 204, 102, 0.1)}:host(.admin-mode.drag-over) .le-slot-dropzone:empty::before{border-color:#00cc66;color:#00cc66;content:'Release to drop'}:host(.admin-mode) .le-slot-input{display:block;padding:var(--le-spacing-1, 4px)}:host(.admin-mode) .le-slot-input input,:host(.admin-mode) .le-slot-input textarea{display:block;width:100%;padding:8px 10px;border:1px solid var(--le-slot-dropzone-border-color);border-radius:4px;font-family:inherit;font-size:14px;line-height:1.4;background:#fff;color:#333;box-sizing:border-box;transition:border-color 0.2s, box-shadow 0.2s}:host(.admin-mode) .le-slot-input input:focus,:host(.admin-mode) .le-slot-input textarea:focus{outline:none;border-color:var(--le-slot-border-color);box-shadow:0 0 0 3px rgba(0, 136, 255, 0.15)}:host(.admin-mode) .le-slot-input input::placeholder,:host(.admin-mode) .le-slot-input textarea::placeholder{color:#999}:host(.admin-mode) .le-slot-input textarea{resize:vertical;min-height:60px}:host(.admin-mode) .le-slot-input slot{display:none}.le-slot-invalid{color:var(--le-slot-required-color);font-size:10px;margin-left:auto;font-weight:normal;text-transform:none}:host(.admin-mode) .le-slot-input.has-error input,:host(.admin-mode) .le-slot-input.has-error textarea{border-color:var(--le-slot-required-color);background:rgba(229, 57, 53, 0.05)}:host(.admin-mode) .le-slot-input.has-error input:focus,:host(.admin-mode) .le-slot-input.has-error textarea:focus{border-color:var(--le-slot-required-color);box-shadow:0 0 0 3px rgba(229, 57, 53, 0.15)}.le-slot-add-btn{font-size:24px;line-height:0px;width:12px;height:12px}.le-slot-header-no-label .le-slot-add-btn{font-size:16px}.le-slot-button{width:20px;height:20px}:host(.admin-mode) .le-slot-header-no-label.le-slot-header-text{height:0}";
|
|
727
|
-
|
|
728
|
-
const LeSlot = class {
|
|
729
|
-
constructor(hostRef) {
|
|
730
|
-
registerInstance(this, hostRef);
|
|
731
|
-
this.leSlotChange = createEvent(this, "leSlotChange");
|
|
779
|
+
// Update local state
|
|
780
|
+
this.propertyValues = { ...this.propertyValues, [attrName]: value };
|
|
732
781
|
}
|
|
733
|
-
get el() { return getElement(this); }
|
|
734
|
-
/**
|
|
735
|
-
* The type of slot content.
|
|
736
|
-
* - `slot`: Default, shows a dropzone for components (default)
|
|
737
|
-
* - `text`: Shows a single-line text input
|
|
738
|
-
* - `textarea`: Shows a multi-line text area
|
|
739
|
-
*/
|
|
740
|
-
type = 'slot';
|
|
741
|
-
/**
|
|
742
|
-
* The name of the slot this placeholder represents.
|
|
743
|
-
* Should match the slot name in the parent component.
|
|
744
|
-
*/
|
|
745
|
-
name = '';
|
|
746
|
-
/**
|
|
747
|
-
* Label to display in admin mode.
|
|
748
|
-
* If not provided, the slot name will be used.
|
|
749
|
-
*/
|
|
750
|
-
label;
|
|
751
|
-
/**
|
|
752
|
-
* Description of what content this slot accepts.
|
|
753
|
-
* Shown in admin mode to guide content editors.
|
|
754
|
-
*/
|
|
755
|
-
description;
|
|
756
|
-
/**
|
|
757
|
-
* Comma-separated list of allowed component tags for this slot.
|
|
758
|
-
* Used by CMS to filter available components.
|
|
759
|
-
*
|
|
760
|
-
* @example "le-card,le-button,le-text"
|
|
761
|
-
*/
|
|
762
|
-
allowedComponents;
|
|
763
|
-
/**
|
|
764
|
-
* Whether multiple components can be dropped in this slot.
|
|
765
|
-
*/
|
|
766
|
-
multiple = true;
|
|
767
|
-
/**
|
|
768
|
-
* Whether this slot is required to have content.
|
|
769
|
-
*/
|
|
770
|
-
required = false;
|
|
771
|
-
/**
|
|
772
|
-
* Placeholder text for text/textarea inputs in admin mode.
|
|
773
|
-
*/
|
|
774
|
-
placeholder;
|
|
775
|
-
/**
|
|
776
|
-
* The HTML tag to create when there's no slotted element.
|
|
777
|
-
* Used with type="text" or type="textarea" to auto-create elements.
|
|
778
|
-
*
|
|
779
|
-
* @example "h3" - creates <h3 slot="header">content</h3>
|
|
780
|
-
* @example "p" - creates <p slot="content">content</p>
|
|
781
|
-
*/
|
|
782
|
-
tag;
|
|
783
|
-
/**
|
|
784
|
-
* CSS styles for the slot dropzone container.
|
|
785
|
-
* Useful for layouts - e.g., "flex-direction: row" for horizontal stacks.
|
|
786
|
-
* Only applies in admin mode for type="slot".
|
|
787
|
-
*/
|
|
788
|
-
slotStyle;
|
|
789
782
|
/**
|
|
790
|
-
*
|
|
791
|
-
*/
|
|
792
|
-
adminMode = false;
|
|
793
|
-
/**
|
|
794
|
-
* Internal state for text input value (synced from slot content)
|
|
795
|
-
*/
|
|
796
|
-
textValue = '';
|
|
797
|
-
/**
|
|
798
|
-
* Whether the current textValue contains valid HTML
|
|
799
|
-
*/
|
|
800
|
-
isValidHtml = true;
|
|
801
|
-
/**
|
|
802
|
-
* Available components loaded from Custom Elements Manifest
|
|
803
|
-
*/
|
|
804
|
-
availableComponents = [];
|
|
805
|
-
/**
|
|
806
|
-
* Whether the component picker popover is open
|
|
807
|
-
*/
|
|
808
|
-
pickerOpen = false;
|
|
809
|
-
/**
|
|
810
|
-
* Reference to the slot element to access assignedNodes
|
|
811
|
-
*/
|
|
812
|
-
slotRef;
|
|
813
|
-
/**
|
|
814
|
-
* The original slotted element (e.g., <h3 slot="header">)
|
|
815
|
-
*/
|
|
816
|
-
slottedElement;
|
|
817
|
-
/**
|
|
818
|
-
* Emitted when text content changes in admin mode.
|
|
819
|
-
* The event detail contains the new text value and validity.
|
|
783
|
+
* Delete this component from the DOM
|
|
820
784
|
*/
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
this.loadAvailableComponents();
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
disconnectedCallback() {
|
|
839
|
-
this.disconnectModeObserver?.();
|
|
785
|
+
deleteComponent() {
|
|
786
|
+
if (!this.hostElement)
|
|
787
|
+
return;
|
|
788
|
+
// Confirm deletion
|
|
789
|
+
const name = this.displayName || this.formatDisplayName(this.component);
|
|
790
|
+
if (!confirm(`Delete this ${name}?`))
|
|
791
|
+
return;
|
|
792
|
+
// Remove the host element from its parent
|
|
793
|
+
const parent = this.hostElement.parentElement;
|
|
794
|
+
if (parent) {
|
|
795
|
+
this.hostElement.remove();
|
|
796
|
+
}
|
|
840
797
|
}
|
|
841
798
|
/**
|
|
842
|
-
*
|
|
799
|
+
* Render the property editor form
|
|
843
800
|
*/
|
|
844
|
-
|
|
801
|
+
renderPropertyEditor() {
|
|
802
|
+
const hasProperties = this.componentMeta && this.componentMeta.attributes.length > 0;
|
|
803
|
+
return (h("div", { class: "property-editor-container" }, hasProperties ? (h("form", { class: "property-editor", onSubmit: e => e.preventDefault() }, this.componentMeta.attributes.map(attr => this.renderPropertyField(attr)))) : (h("p", { class: "no-properties" }, "No editable properties")), h("div", { class: "property-editor-actions" }, h("le-button", { type: "button", variant: "outlined", color: "danger", "full-width": true, onClick: () => this.deleteComponent() }, h("span", { slot: "icon-start" }, "\uD83D\uDDD1\uFE0F"), h("span", null, "Delete Component")))));
|
|
804
|
+
}
|
|
845
805
|
/**
|
|
846
|
-
*
|
|
806
|
+
* Render a single property field based on its type
|
|
847
807
|
*/
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
//
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
808
|
+
renderPropertyField(attr) {
|
|
809
|
+
const value = this.propertyValues[attr.name];
|
|
810
|
+
const type = attr.type?.text || 'string';
|
|
811
|
+
// Check if type is a union of string literals (e.g., "'default' | 'outlined' | 'elevated'")
|
|
812
|
+
const enumMatch = type.match(/^'[^']+'/);
|
|
813
|
+
if (enumMatch) {
|
|
814
|
+
const options = type.split('|').map(opt => opt.trim().replace(/'/g, ''));
|
|
815
|
+
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))))));
|
|
855
816
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
if (this.slottedElement !== elementNode) {
|
|
864
|
-
this.slottedElement = elementNode;
|
|
865
|
-
this.textValue = elementNode.innerHTML?.trim() || '';
|
|
866
|
-
// console.log(`[le-slot "${this.name}"] Read slotted content:`, this.textValue);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
else {
|
|
870
|
-
// No element, check for direct text content
|
|
871
|
-
const textContent = assignedNodes
|
|
872
|
-
.filter(node => node.nodeType === Node.TEXT_NODE)
|
|
873
|
-
.map(node => node.textContent)
|
|
874
|
-
.join('')
|
|
875
|
-
.trim();
|
|
876
|
-
if (textContent && !this.textValue) {
|
|
877
|
-
this.textValue = textContent;
|
|
878
|
-
// console.log(`[le-slot "${this.name}"] Read text content:`, this.textValue);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
817
|
+
// Boolean type
|
|
818
|
+
if (type === 'boolean') {
|
|
819
|
+
return (h("div", { class: "property-field property-field--checkbox" }, h("le-checkbox", { name: `prop-${attr.name}`, checked: value === true || value === '', onChange: e => this.handlePropertyChange(attr.name, e.target.checked, type) }, attr.name, attr.description && h("div", { slot: "description" }, attr.description))));
|
|
820
|
+
}
|
|
821
|
+
// Number type
|
|
822
|
+
if (type === 'number') {
|
|
823
|
+
return (h("div", { class: "property-field" }, h("label", { htmlFor: `prop-${attr.name}` }, attr.name, attr.description && h("span", { class: "property-hint" }, attr.description)), h("input", { type: "number", id: `prop-${attr.name}`, value: value ?? '', placeholder: attr.default, onChange: e => this.handlePropertyChange(attr.name, e.target.value, type) })));
|
|
881
824
|
}
|
|
825
|
+
// Default: string/text input
|
|
826
|
+
return (h("div", { class: "property-field" }, h("le-string-input", { name: `prop-${attr.name}`, label: attr.name, value: value ?? '', placeholder: attr.default?.replace(/'/g, ''), onChange: (e) => this.handlePropertyChange(attr.name, e.detail.value, type) }, h("span", { slot: "description" }, attr.description))));
|
|
882
827
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (!html.trim())
|
|
889
|
-
return true;
|
|
890
|
-
// Create a template element to parse the HTML
|
|
891
|
-
const template = document.createElement('template');
|
|
892
|
-
template.innerHTML = html;
|
|
893
|
-
// Check that we don't have obviously broken HTML
|
|
894
|
-
// Count opening and closing tags for common elements
|
|
895
|
-
const openTags = (html.match(/<[a-z][^>]*(?<!\/)>/gi) || []).length;
|
|
896
|
-
const closeTags = (html.match(/<\/[a-z][^>]*>/gi) || []).length;
|
|
897
|
-
const selfClosing = (html.match(/<[a-z][^>]*\/>/gi) || []).length;
|
|
898
|
-
// Simple validation: opening tags (minus self-closing) should roughly match closing tags
|
|
899
|
-
// Allow some tolerance for void elements like <br>, <img>, etc.
|
|
900
|
-
const voidElements = (html.match(/<(br|hr|img|input|meta|link|area|base|col|embed|param|source|track|wbr)[^>]*>/gi) || []).length;
|
|
901
|
-
const effectiveOpenTags = openTags - selfClosing - voidElements;
|
|
902
|
-
// If difference is too large, HTML is likely broken
|
|
903
|
-
if (Math.abs(effectiveOpenTags - closeTags) > 1) {
|
|
904
|
-
return false;
|
|
828
|
+
render() {
|
|
829
|
+
const name = this.displayName || this.formatDisplayName(this.component);
|
|
830
|
+
// In default mode, just pass through content with host classes
|
|
831
|
+
if (!this.adminMode) {
|
|
832
|
+
return (h(Host, { class: classnames(this.component, this.hostClass), style: this.hostStyle }, h("slot", null)));
|
|
905
833
|
}
|
|
906
|
-
|
|
834
|
+
// In admin mode, show wrapper with header and settings
|
|
835
|
+
return (h(Host, { class: classnames(this.component, this.hostClass, 'admin-mode'), style: this.hostStyle }, h("div", { class: "le-component-wrapper" }, h("div", { class: "le-component-header" }, h("span", { class: "le-component-name" }, name), h("le-popover", { popoverTitle: `${name} Settings`, position: "right", align: "start", "min-width": "300px", mode: "default" }, h("le-button", { type: "button", class: "le-component-button", slot: "trigger", variant: "clear", size: "small", "aria-label": "Edit component properties", "icon-only": true }, h("span", { class: "le-component-trigger", slot: "icon-only" }, "\u2699")), this.renderPropertyEditor())), h("div", { class: "le-component-content" }, h("slot", null)))));
|
|
907
836
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
837
|
+
static get assetsDirs() { return ["assets"]; }
|
|
838
|
+
static get style() { return leComponentCss; }
|
|
839
|
+
}, [769, "le-component", {
|
|
840
|
+
"component": [1],
|
|
841
|
+
"displayName": [1, "display-name"],
|
|
842
|
+
"hostClass": [1, "host-class"],
|
|
843
|
+
"hostStyle": [16],
|
|
844
|
+
"adminMode": [32],
|
|
845
|
+
"componentMeta": [32],
|
|
846
|
+
"propertyValues": [32]
|
|
847
|
+
}]);
|
|
848
|
+
function defineCustomElement$2() {
|
|
849
|
+
if (typeof customElements === "undefined") {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
const components = ["le-component", "le-button", "le-checkbox", "le-component", "le-popover", "le-slot", "le-string-input"];
|
|
853
|
+
components.forEach(tagName => { switch (tagName) {
|
|
854
|
+
case "le-component":
|
|
855
|
+
if (!customElements.get(tagName)) {
|
|
856
|
+
customElements.define(tagName, LeComponent);
|
|
919
857
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
const rootNode = this.el.getRootNode();
|
|
925
|
-
if (!this.name && rootNode instanceof ShadowRoot) {
|
|
926
|
-
const hostComponent = rootNode.host;
|
|
927
|
-
Array.from(hostComponent.childNodes).forEach(node => {
|
|
928
|
-
if (node.nodeType === Node.TEXT_NODE || (node.nodeType === Node.ELEMENT_NODE && !node.hasAttribute('slot'))) {
|
|
929
|
-
node.remove();
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
// create one using the specified tag
|
|
934
|
-
this.createSlottedElement();
|
|
858
|
+
break;
|
|
859
|
+
case "le-button":
|
|
860
|
+
if (!customElements.get(tagName)) {
|
|
861
|
+
defineCustomElement();
|
|
935
862
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
const hostComponent = rootNode.host;
|
|
941
|
-
hostComponent.innerHTML = this.textValue;
|
|
942
|
-
}
|
|
863
|
+
break;
|
|
864
|
+
case "le-checkbox":
|
|
865
|
+
if (!customElements.get(tagName)) {
|
|
866
|
+
defineCustomElement$1();
|
|
943
867
|
}
|
|
868
|
+
break;
|
|
869
|
+
case "le-component":
|
|
870
|
+
if (!customElements.get(tagName)) {
|
|
871
|
+
defineCustomElement$2();
|
|
872
|
+
}
|
|
873
|
+
break;
|
|
874
|
+
case "le-popover":
|
|
875
|
+
if (!customElements.get(tagName)) {
|
|
876
|
+
defineCustomElement$5();
|
|
877
|
+
}
|
|
878
|
+
break;
|
|
879
|
+
case "le-slot":
|
|
880
|
+
if (!customElements.get(tagName)) {
|
|
881
|
+
defineCustomElement$3();
|
|
882
|
+
}
|
|
883
|
+
break;
|
|
884
|
+
case "le-string-input":
|
|
885
|
+
if (!customElements.get(tagName)) {
|
|
886
|
+
defineCustomElement$4();
|
|
887
|
+
}
|
|
888
|
+
break;
|
|
889
|
+
} });
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const leCheckboxCss = ":host{display:block;--le-checkbox-size:18px;--le-checkbox-color:var(--le-color-primary, #007bff);--le-checkbox-label-color:var(--le-color-text-primary, #333);--le-checkbox-desc-color:var(--le-color-text-secondary, #666);--le-checkbox-border-radius:var(--le-radius-sm, 2px);--le-checkbox-marker-color:var(--le-color-surface, #fff)}.le-checkbox-wrapper{display:flex;flex-direction:column;gap:4px}.le-checkbox-label{display:inline-flex;align-items:flex-start;gap:8px;cursor:pointer;user-select:none}:host([disabled]) .le-checkbox-label{cursor:not-allowed;opacity:0.6}.le-checkbox-input{display:flex;align-items:center;justify-content:center;min-height:1.4em}input[type=\"checkbox\"]{appearance:none;-webkit-appearance:none;width:var(--le-checkbox-size);height:var(--le-checkbox-size);border:var(--le-border-width, 2px) solid var(--le-checkbox-color);border-radius:var(--le-checkbox-border-radius);margin:0;margin-top:2px;position:relative;cursor:inherit;background-color:transparent;transition:background-color 0.2s, border-color 0.2s}input[type=\"checkbox\"]:checked{background-color:var(--le-checkbox-color)}input[type=\"checkbox\"]:checked::after{content:'';position:absolute;left:0;top:0;bottom:calc(var(--le-checkbox-size) / 5);right:0;margin:auto;width:calc(var(--le-checkbox-size) / 4);height:calc(var(--le-checkbox-size) / 2);border:solid var(--le-checkbox-marker-color, #fff);border-width:0 calc(var(--le-checkbox-size) / 10) calc(var(--le-checkbox-size) / 10) 0;transform:rotate(45deg)}input[type=\"checkbox\"]:focus-visible{outline:2px solid var(--le-color-focus);outline-offset:2px}.le-checkbox-text{flex:1;flex-wrap:wrap;color:var(--le-checkbox-label-color);line-height:1.5;text-align:start}.le-checkbox-description{margin-left:calc(var(--le-checkbox-size) + 8px);font-size:0.875em;color:var(--le-checkbox-desc-color);line-height:1.4}:host [slot=\"description\"]{margin:0}";
|
|
893
|
+
|
|
894
|
+
const LeCheckbox = /*@__PURE__*/ proxyCustomElement(class LeCheckbox extends HTMLElement {
|
|
895
|
+
constructor(registerHost) {
|
|
896
|
+
super();
|
|
897
|
+
if (registerHost !== false) {
|
|
898
|
+
this.__registerHost();
|
|
944
899
|
}
|
|
945
|
-
this.
|
|
946
|
-
|
|
947
|
-
value: this.textValue,
|
|
948
|
-
isValid: this.isValidHtml,
|
|
949
|
-
});
|
|
950
|
-
};
|
|
951
|
-
/**
|
|
952
|
-
* Create a new slotted element when none exists.
|
|
953
|
-
* The element is appended to the host component's light DOM.
|
|
954
|
-
*/
|
|
955
|
-
createSlottedElement() {
|
|
956
|
-
if (!this.tag)
|
|
957
|
-
return;
|
|
958
|
-
// Find the host component (le-card, etc.) by traversing up through shadow DOM
|
|
959
|
-
// le-slot is inside le-card's shadow DOM, so we need to find le-card's host
|
|
960
|
-
const rootNode = this.el.getRootNode();
|
|
961
|
-
if (!(rootNode instanceof ShadowRoot))
|
|
962
|
-
return;
|
|
963
|
-
const hostComponent = rootNode.host;
|
|
964
|
-
if (!hostComponent)
|
|
965
|
-
return;
|
|
966
|
-
// Create the new element
|
|
967
|
-
const newElement = document.createElement(this.tag);
|
|
968
|
-
newElement.innerHTML = this.textValue;
|
|
969
|
-
// Set the slot attribute if this is a named slot
|
|
970
|
-
if (this.name) {
|
|
971
|
-
newElement.setAttribute('slot', this.name);
|
|
972
|
-
}
|
|
973
|
-
// Append to the host component's light DOM
|
|
974
|
-
hostComponent.appendChild(newElement);
|
|
975
|
-
// Store reference to the new element
|
|
976
|
-
this.slottedElement = newElement;
|
|
977
|
-
// console.log(`[le-slot "${this.name}"] Created new <${this.tag}> element`);
|
|
900
|
+
this.__attachShadow();
|
|
901
|
+
this.leChange = createEvent(this, "change", 7);
|
|
978
902
|
}
|
|
903
|
+
get el() { return this; }
|
|
979
904
|
/**
|
|
980
|
-
*
|
|
905
|
+
* Whether the checkbox is checked
|
|
981
906
|
*/
|
|
982
|
-
|
|
983
|
-
try {
|
|
984
|
-
const { manifestUrl } = getLeKitConfig();
|
|
985
|
-
const manifestUrlResolved = manifestUrl.startsWith('/')
|
|
986
|
-
? getAssetPath(`./assets${manifestUrl}`)
|
|
987
|
-
: manifestUrl;
|
|
988
|
-
const response = await fetch(manifestUrlResolved);
|
|
989
|
-
const manifest = await response.json();
|
|
990
|
-
const components = [];
|
|
991
|
-
const allowedList = this.allowedComponents?.split(',').map(s => s.trim()) || [];
|
|
992
|
-
for (const module of manifest.modules) {
|
|
993
|
-
for (const declaration of module.declarations || []) {
|
|
994
|
-
if (declaration.tagName && declaration.customElement) {
|
|
995
|
-
// Skip internal components (le-slot, le-component, le-popover)
|
|
996
|
-
const isInternal = ['le-slot', 'le-component', 'le-popover'].includes(declaration.tagName);
|
|
997
|
-
if (isInternal)
|
|
998
|
-
continue;
|
|
999
|
-
// If allowedComponents is specified, filter by it
|
|
1000
|
-
if (allowedList.length > 0 && !allowedList.includes(declaration.tagName)) {
|
|
1001
|
-
continue;
|
|
1002
|
-
}
|
|
1003
|
-
components.push({
|
|
1004
|
-
tagName: declaration.tagName,
|
|
1005
|
-
name: this.formatComponentName(declaration.tagName),
|
|
1006
|
-
description: declaration.description || '',
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
this.availableComponents = components || [];
|
|
1012
|
-
}
|
|
1013
|
-
catch (error) {
|
|
1014
|
-
console.warn('[le-slot] Failed to load component manifest:', error);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
907
|
+
checked = false;
|
|
1017
908
|
/**
|
|
1018
|
-
*
|
|
1019
|
-
* e.g., 'le-card' -> 'Card'
|
|
909
|
+
* Whether the checkbox is disabled
|
|
1020
910
|
*/
|
|
1021
|
-
|
|
1022
|
-
return tagName
|
|
1023
|
-
.replace(/^le-/, '')
|
|
1024
|
-
.split('-')
|
|
1025
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
1026
|
-
.join(' ');
|
|
1027
|
-
}
|
|
911
|
+
disabled = false;
|
|
1028
912
|
/**
|
|
1029
|
-
*
|
|
913
|
+
* The name of the checkbox input
|
|
1030
914
|
*/
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
915
|
+
name;
|
|
916
|
+
/**
|
|
917
|
+
* The value of the checkbox input
|
|
918
|
+
*/
|
|
919
|
+
value;
|
|
920
|
+
/**
|
|
921
|
+
* External ID for linking with external systems (e.g. database ID, PDF form field ID)
|
|
922
|
+
*/
|
|
923
|
+
externalId;
|
|
924
|
+
/**
|
|
925
|
+
* Emitted when the checked state changes
|
|
926
|
+
*/
|
|
927
|
+
leChange;
|
|
928
|
+
handleChange = (event) => {
|
|
929
|
+
// We stop the internal button click from bubbling up
|
|
930
|
+
event.stopPropagation();
|
|
931
|
+
if (this.disabled) {
|
|
932
|
+
event.preventDefault();
|
|
1038
933
|
return;
|
|
1039
|
-
// Create the new component element
|
|
1040
|
-
const newElement = document.createElement(tagName);
|
|
1041
|
-
// Set the slot attribute if this is a named slot
|
|
1042
|
-
if (this.name) {
|
|
1043
|
-
newElement.setAttribute('slot', this.name);
|
|
1044
934
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
935
|
+
const input = event.target;
|
|
936
|
+
this.checked = input.checked;
|
|
937
|
+
this.leChange.emit({
|
|
938
|
+
checked: this.checked,
|
|
939
|
+
value: this.value,
|
|
1049
940
|
name: this.name,
|
|
1050
|
-
|
|
1051
|
-
isValid: true,
|
|
941
|
+
externalId: this.externalId
|
|
1052
942
|
});
|
|
1053
|
-
}
|
|
1054
|
-
/**
|
|
1055
|
-
* Handle slot change event to re-read content when nodes are assigned
|
|
1056
|
-
*/
|
|
1057
|
-
handleSlotChange = () => {
|
|
1058
|
-
this.readSlottedContent();
|
|
1059
943
|
};
|
|
1060
944
|
render() {
|
|
1061
|
-
|
|
1062
|
-
// Always render the same structure, CSS handles visibility via .admin-mode class
|
|
1063
|
-
return (h(Host, { key: 'e89effa647f07ae271cffc05aad6730b51da6447', class: {
|
|
1064
|
-
'admin-mode': this.adminMode,
|
|
1065
|
-
'invalid-html': !this.isValidHtml,
|
|
1066
|
-
}, role: this.adminMode ? 'region' : undefined, "aria-label": this.adminMode ? `Slot: ${displayLabel}` : undefined, "data-slot-name": this.name, "data-slot-type": this.type, "data-allowed": this.allowedComponents, "data-multiple": this.multiple, "data-required": this.required }, this.adminMode ? (h("div", { class: "le-slot-container" }, h("div", { class: classnames('le-slot-header', {
|
|
1067
|
-
'le-slot-header-no-label': !displayLabel,
|
|
1068
|
-
'le-slot-header-text': this.type === 'text',
|
|
1069
|
-
'le-slot-header-error': !this.isValidHtml,
|
|
1070
|
-
}) }, displayLabel && (h("span", { class: "le-slot-label" }, displayLabel, this.required && h("span", { class: "le-slot-required" }, "*"))), !this.isValidHtml && h("span", { class: "le-slot-invalid" }, "\u26A0 Invalid HTML"), this.type === 'slot' && this.adminMode && (h("le-popover", { mode: "default", showClose: true, align: "start", position: "right", popoverTitle: "Add Component", open: this.pickerOpen, onLePopoverOpen: () => (this.pickerOpen = true), onLePopoverClose: () => (this.pickerOpen = false) }, h("le-button", { type: "button", class: "le-slot-button", slot: "trigger", variant: "clear", size: "small", "aria-label": "Add component", "icon-only": true }, h("span", { class: "le-slot-add-btn", slot: "icon-only" }, "+")), h("div", { class: "le-slot-picker" }, this.availableComponents.length > 0 ? (h("ul", { class: "le-slot-picker-list" }, this.availableComponents.map(component => (h("li", { key: component.tagName }, h("button", { class: "le-slot-picker-item", onClick: () => {
|
|
1071
|
-
this.addComponent(component.tagName);
|
|
1072
|
-
this.pickerOpen = false;
|
|
1073
|
-
} }, h("span", { class: "le-slot-picker-name" }, component.name), component.description && h("span", { class: "le-slot-picker-desc" }, component.description))))))) : (h("div", { class: "le-slot-picker-empty" }, "No components available")))))), this.renderContent())) : (
|
|
1074
|
-
// In default mode, just pass through the slot - slotted content renders naturally
|
|
1075
|
-
// Note: We use unnamed slot here because named slots from parent component
|
|
1076
|
-
// are passed as le-slot's light DOM children
|
|
1077
|
-
h("slot", null))));
|
|
945
|
+
return (h("le-component", { key: '43399929e07835e0019d509803e50a151921fa72', component: "le-checkbox", hostClass: classnames({ 'disabled': this.disabled }) }, h("div", { key: '7ddbf2ac1690bb09082adfea70b9767c972d007a', class: "le-checkbox-wrapper" }, h("label", { key: '8eec4055c713e8b3b155695751b10bff64c9f903', class: "le-checkbox-label" }, h("span", { key: '2118b1cbe7911ff1674e522d723949d81cade185', class: "le-checkbox-input" }, h("input", { key: 'd0a30af5c14497fa6fa294c07ba74ae2e032481f', type: "checkbox", name: this.name, value: this.value, checked: this.checked, disabled: this.disabled, onChange: this.handleChange })), h("span", { key: '02cf9588431240039a53ee50e02b08ba5d63b974', class: "le-checkbox-text" }, h("le-slot", { key: 'e7d7b253deab72e627164eb72fc06109abfca6a5', name: "", type: "text", tag: "span" }, h("slot", { key: '1d8c443073e48848513a8a6d04cd7805a394e54e' })))), h("div", { key: '16c2c927dc0c0f7844a203a0628bf0e561009bd0', class: "le-checkbox-description" }, h("le-slot", { key: 'c6898ecc8992dce4786e68ab4b136bf5c3a4d3aa', name: "description", type: "text", tag: "div", label: "Description" }, h("slot", { key: '3342add8ed1400ab74681e445163eeb3dd415941', name: "description" }))))));
|
|
1078
946
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
case 'slot':
|
|
1091
|
-
default:
|
|
1092
|
-
// Parse slotStyle string into style object if provided
|
|
1093
|
-
const dropzoneStyle = {};
|
|
1094
|
-
if (this.slotStyle) {
|
|
1095
|
-
this.slotStyle.split(';').forEach(rule => {
|
|
1096
|
-
const [prop, value] = rule.split(':').map(s => s.trim());
|
|
1097
|
-
if (prop && value) {
|
|
1098
|
-
// Convert kebab-case to camelCase for style object
|
|
1099
|
-
const camelProp = prop.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1100
|
-
dropzoneStyle[camelProp] = value;
|
|
1101
|
-
}
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
return (h("div", { class: "le-slot-dropzone", style: dropzoneStyle }, h("slot", { ref: el => (this.slotRef = el), onSlotchange: this.handleSlotChange })));
|
|
1105
|
-
}
|
|
947
|
+
static get style() { return leCheckboxCss; }
|
|
948
|
+
}, [769, "le-checkbox", {
|
|
949
|
+
"checked": [1540],
|
|
950
|
+
"disabled": [4],
|
|
951
|
+
"name": [1],
|
|
952
|
+
"value": [1],
|
|
953
|
+
"externalId": [1, "external-id"]
|
|
954
|
+
}]);
|
|
955
|
+
function defineCustomElement$1() {
|
|
956
|
+
if (typeof customElements === "undefined") {
|
|
957
|
+
return;
|
|
1106
958
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
959
|
+
const components = ["le-checkbox", "le-button", "le-checkbox", "le-component", "le-popover", "le-slot", "le-string-input"];
|
|
960
|
+
components.forEach(tagName => { switch (tagName) {
|
|
961
|
+
case "le-checkbox":
|
|
962
|
+
if (!customElements.get(tagName)) {
|
|
963
|
+
customElements.define(tagName, LeCheckbox);
|
|
964
|
+
}
|
|
965
|
+
break;
|
|
966
|
+
case "le-button":
|
|
967
|
+
if (!customElements.get(tagName)) {
|
|
968
|
+
defineCustomElement();
|
|
969
|
+
}
|
|
970
|
+
break;
|
|
971
|
+
case "le-checkbox":
|
|
972
|
+
if (!customElements.get(tagName)) {
|
|
973
|
+
defineCustomElement$1();
|
|
974
|
+
}
|
|
975
|
+
break;
|
|
976
|
+
case "le-component":
|
|
977
|
+
if (!customElements.get(tagName)) {
|
|
978
|
+
defineCustomElement$2();
|
|
979
|
+
}
|
|
980
|
+
break;
|
|
981
|
+
case "le-popover":
|
|
982
|
+
if (!customElements.get(tagName)) {
|
|
983
|
+
defineCustomElement$5();
|
|
984
|
+
}
|
|
985
|
+
break;
|
|
986
|
+
case "le-slot":
|
|
987
|
+
if (!customElements.get(tagName)) {
|
|
988
|
+
defineCustomElement$3();
|
|
989
|
+
}
|
|
990
|
+
break;
|
|
991
|
+
case "le-string-input":
|
|
992
|
+
if (!customElements.get(tagName)) {
|
|
993
|
+
defineCustomElement$4();
|
|
994
|
+
}
|
|
995
|
+
break;
|
|
996
|
+
} });
|
|
997
|
+
}
|
|
1109
998
|
|
|
1110
|
-
const
|
|
999
|
+
const leButtonDefaultCss = ":host{display:inline-block;--le-button-border-radius:var(--le-radius-md);--le-button-padding-x:0.4rem;--le-button-padding-y:0.4rem;--le-button-small-padding:0.25rem;--le-button-font-size:var(--le-font-size-md);--le-button-font-weight:var(--le-font-weight-medium);--le-button-transition:var(--le-transition-fast);--le-button-icon-aspect-ratio:1;--_btn-bg:var(--le-color-primary);--_btn-bg-hover:var(--le-color-primary-dark);--_btn-bg-system:var(--le-color-black);--_btn-color:var(--le-color-primary-contrast);--_btn-border-color:var(--le-color-primary)}:host([full-width]){display:block;width:100%}.button{display:inline-flex;align-items:center;justify-content:center;gap:var(--le-spacing-3);width:100%;padding:var(--le-button-padding-y) var(--le-button-padding-x);border:1px solid var(--_btn-border-color);border-radius:var(--le-button-border-radius);background:var(--_btn-bg);color:var(--_btn-color);font-family:var(--le-font-family-base);font-size:var(--le-button-font-size);font-weight:var(--le-button-font-weight);line-height:var(--le-line-height-tight);text-decoration:none;cursor:pointer;transition:background-color var(--le-button-transition) var(--le-transition-easing),\n border-color var(--le-button-transition) var(--le-transition-easing),\n box-shadow var(--le-button-transition) var(--le-transition-easing),\n transform var(--le-button-transition) var(--le-transition-easing)}.button:hover:not(:disabled){background:var(--_btn-bg-hover);border-color:var(--_btn-bg-hover)}.button:active:not(:disabled){transform:translateY(1px)}.button:focus-visible{outline:2px solid var(--le-color-focus);outline-offset:2px}.button:disabled{opacity:0.5;cursor:not-allowed}:host>le-component.color-primary{--_btn-bg:var(--le-color-primary);--_btn-bg-hover:var(--le-color-primary-dark);--_btn-color:var(--le-color-primary-contrast);--_btn-border-color:var(--le-color-primary)}:host>le-component.color-secondary{--_btn-bg:var(--le-color-secondary);--_btn-bg-hover:var(--le-color-secondary-dark);--_btn-color:var(--le-color-secondary-contrast);--_btn-border-color:var(--le-color-secondary)}:host>le-component.color-success{--_btn-bg:var(--le-color-success);--_btn-bg-hover:var(--le-color-success-dark);--_btn-color:var(--le-color-success-contrast);--_btn-border-color:var(--le-color-success)}:host>le-component.color-warning{--_btn-bg:var(--le-color-warning);--_btn-bg-hover:var(--le-color-warning-dark);--_btn-color:var(--le-color-warning-contrast);--_btn-border-color:var(--le-color-warning)}:host>le-component.color-danger{--_btn-bg:var(--le-color-danger);--_btn-bg-hover:var(--le-color-danger-dark);--_btn-color:var(--le-color-danger-contrast);--_btn-border-color:var(--le-color-danger)}:host>le-component.color-info{--_btn-bg:var(--le-color-info);--_btn-bg-hover:var(--le-color-info-dark);--_btn-color:var(--le-color-info-contrast);--_btn-border-color:var(--le-color-info)}:host>le-component.variant-solid .button{box-shadow:var(--le-shadow-sm)}:host>le-component.variant-solid .button:hover:not(:disabled){box-shadow:var(--le-shadow-md)}:host>le-component.variant-outlined .button{background:transparent;color:var(--_btn-bg);border-color:var(--_btn-border-color)}:host>le-component.variant-outlined .button:hover:not(:disabled){background:var(--_btn-bg);color:var(--_btn-color)}:host>le-component.variant-clear .button{background:transparent;color:var(--_btn-bg);border-color:transparent}:host>le-component.variant-clear .button:hover:not(:disabled){background:var(--le-color-gray-100);border-color:transparent}:host>le-component.variant-system .button{background:transparent;color:var(--_btn-bg-system);border-color:transparent}:host>le-component.size-small .button{--le-button-padding-x:0.4rem;--le-button-padding-y:0.3rem;--le-button-padding-top:0.35rem;--le-button-font-size:var(--le-button-small-font-size, var(--le-font-size-xs))}:host>le-component.size-large .button{--le-button-padding-x:0.9rem;--le-button-padding-y:0.6rem;--le-button-font-size:var(--le-font-size-xl)}:host>le-component.full-width{display:block;width:100%}:host>le-component.selected .button{box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.2)}:host>le-component.variant-outlined.selected .button,:host>le-component.variant-clear.selected .button{background:var(--_btn-bg);color:var(--_btn-color)}:host>le-component.icon-only .button{padding:0.5rem;padding-bottom:0.6rem;aspect-ratio:var(--le-button-icon-aspect-ratio, 1)}:host>le-component.icon-only.size-small .button{padding:var(--le-button-small-padding, 0.25rem)}:host>le-component.icon-only.size-large .button{padding:0.75rem}:host>le-component.icon-only .content{display:none}.content{display:inline}.content:empty{display:none}.icon-start,.icon-only,.icon-end{display:flex;align-items:center;justify-content:center}.icon-start:empty,.icon-only:empty,.icon-end:empty{display:none}::slotted([slot=\"icon-start\"]),::slotted([slot=\"icon-only\"]),::slotted([slot=\"icon-end\"]){display:flex;align-items:center;justify-content:center;width:1.125em;height:1.125em}";
|
|
1111
1000
|
|
|
1112
|
-
const
|
|
1113
|
-
constructor(
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1001
|
+
const LeButton = /*@__PURE__*/ proxyCustomElement(class LeButton extends HTMLElement {
|
|
1002
|
+
constructor(registerHost) {
|
|
1003
|
+
super();
|
|
1004
|
+
if (registerHost !== false) {
|
|
1005
|
+
this.__registerHost();
|
|
1006
|
+
}
|
|
1007
|
+
this.__attachShadow();
|
|
1008
|
+
this.leClick = createEvent(this, "click", 7);
|
|
1117
1009
|
}
|
|
1118
|
-
get el() { return
|
|
1010
|
+
get el() { return this; }
|
|
1119
1011
|
/**
|
|
1120
1012
|
* Mode of the popover should be 'default' for internal use
|
|
1121
1013
|
*/
|
|
1122
1014
|
mode;
|
|
1123
1015
|
/**
|
|
1124
|
-
*
|
|
1125
|
-
|
|
1126
|
-
value;
|
|
1127
|
-
/**
|
|
1128
|
-
* The name of the input
|
|
1016
|
+
* Button variant style
|
|
1017
|
+
* @allowedValues solid | outlined | clear
|
|
1129
1018
|
*/
|
|
1130
|
-
|
|
1019
|
+
variant = 'solid';
|
|
1131
1020
|
/**
|
|
1132
|
-
*
|
|
1021
|
+
* Button color theme (uses theme semantic colors)
|
|
1022
|
+
* @allowedValues primary | secondary | success | warning | danger | info
|
|
1133
1023
|
*/
|
|
1134
|
-
|
|
1024
|
+
color = 'primary';
|
|
1135
1025
|
/**
|
|
1136
|
-
*
|
|
1026
|
+
* Button size
|
|
1027
|
+
* @allowedValues small | medium | large
|
|
1137
1028
|
*/
|
|
1138
|
-
|
|
1029
|
+
size = 'medium';
|
|
1139
1030
|
/**
|
|
1140
|
-
*
|
|
1031
|
+
* Whether the button is in a selected/active state
|
|
1141
1032
|
*/
|
|
1142
|
-
|
|
1033
|
+
selected = false;
|
|
1143
1034
|
/**
|
|
1144
|
-
*
|
|
1035
|
+
* Whether the button takes full width of its container
|
|
1145
1036
|
*/
|
|
1146
|
-
|
|
1037
|
+
fullWidth = false;
|
|
1147
1038
|
/**
|
|
1148
|
-
*
|
|
1039
|
+
* Whether the button displays only an icon (square aspect ratio)
|
|
1149
1040
|
*/
|
|
1150
|
-
|
|
1041
|
+
iconOnly = false;
|
|
1151
1042
|
/**
|
|
1152
|
-
* Whether the
|
|
1043
|
+
* Whether the button is disabled
|
|
1153
1044
|
*/
|
|
1154
1045
|
disabled = false;
|
|
1155
1046
|
/**
|
|
1156
|
-
*
|
|
1047
|
+
* The button type attribute
|
|
1048
|
+
* @allowedValues button | submit | reset
|
|
1157
1049
|
*/
|
|
1158
|
-
|
|
1050
|
+
type = 'button';
|
|
1159
1051
|
/**
|
|
1160
|
-
*
|
|
1052
|
+
* Optional href to make the button act as a link
|
|
1161
1053
|
*/
|
|
1162
|
-
|
|
1054
|
+
href;
|
|
1163
1055
|
/**
|
|
1164
|
-
*
|
|
1056
|
+
* Link target when href is set
|
|
1165
1057
|
*/
|
|
1166
|
-
|
|
1058
|
+
target;
|
|
1167
1059
|
/**
|
|
1168
|
-
* Emitted when the
|
|
1060
|
+
* Emitted when the button is clicked.
|
|
1061
|
+
* This is a custom event that wraps the native click but ensures the target is the le-button.
|
|
1169
1062
|
*/
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
this.
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
handleChange = (ev) => {
|
|
1181
|
-
const input = ev.target;
|
|
1182
|
-
this.value = input.value;
|
|
1183
|
-
this.leChange.emit({
|
|
1184
|
-
value: this.value,
|
|
1185
|
-
name: this.name,
|
|
1186
|
-
externalId: this.externalId
|
|
1187
|
-
});
|
|
1188
|
-
};
|
|
1189
|
-
handleClick = (ev) => {
|
|
1190
|
-
ev.stopPropagation();
|
|
1063
|
+
leClick;
|
|
1064
|
+
handleClick = (event) => {
|
|
1065
|
+
// We stop the internal button click from bubbling up
|
|
1066
|
+
event.stopPropagation();
|
|
1067
|
+
if (this.disabled) {
|
|
1068
|
+
event.preventDefault();
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
// And emit our own click event from the host element
|
|
1072
|
+
this.leClick.emit(event);
|
|
1191
1073
|
};
|
|
1192
1074
|
render() {
|
|
1193
|
-
|
|
1075
|
+
const classes = classnames(`variant-${this.variant}`, `color-${this.color}`, `size-${this.size}`, {
|
|
1076
|
+
'selected': this.selected,
|
|
1077
|
+
'full-width': this.fullWidth,
|
|
1078
|
+
'icon-only': this.iconOnly,
|
|
1079
|
+
'disabled': this.disabled,
|
|
1080
|
+
});
|
|
1081
|
+
const TagType = this.href ? 'a' : 'button';
|
|
1082
|
+
const attrs = this.href ? { href: this.href, target: this.target, role: 'button' } : { type: this.type, disabled: this.disabled };
|
|
1083
|
+
return (h("le-component", { key: '363dbfddf4a765bfd6f36ed16d0912e281153806', component: "le-button", hostClass: classes }, h(TagType, { key: 'e112acdff4278e976ad767bd1ea7c9ced5e85f43', class: "button", part: "button", ...attrs, onClick: this.handleClick }, this.iconOnly ? (h("span", { class: "icon-start" }, h("slot", { name: "icon-only" }))) : (h(Fragment, null, h("span", { class: "icon-start" }, h("slot", { name: "icon-start" })), h("le-slot", { name: "", description: "Button text", type: "text", class: "content", part: "content" }, h("slot", null)), h("span", { class: "icon-end" }, h("slot", { name: "icon-end" })))))));
|
|
1084
|
+
}
|
|
1085
|
+
static get style() { return leButtonDefaultCss; }
|
|
1086
|
+
}, [769, "le-button", {
|
|
1087
|
+
"mode": [1537],
|
|
1088
|
+
"variant": [1],
|
|
1089
|
+
"color": [1],
|
|
1090
|
+
"size": [1],
|
|
1091
|
+
"selected": [4],
|
|
1092
|
+
"fullWidth": [516, "full-width"],
|
|
1093
|
+
"iconOnly": [4, "icon-only"],
|
|
1094
|
+
"disabled": [4],
|
|
1095
|
+
"type": [1],
|
|
1096
|
+
"href": [1],
|
|
1097
|
+
"target": [1]
|
|
1098
|
+
}]);
|
|
1099
|
+
function defineCustomElement() {
|
|
1100
|
+
if (typeof customElements === "undefined") {
|
|
1101
|
+
return;
|
|
1194
1102
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1103
|
+
const components = ["le-button", "le-button", "le-checkbox", "le-component", "le-popover", "le-slot", "le-string-input"];
|
|
1104
|
+
components.forEach(tagName => { switch (tagName) {
|
|
1105
|
+
case "le-button":
|
|
1106
|
+
if (!customElements.get(tagName)) {
|
|
1107
|
+
customElements.define(tagName, LeButton);
|
|
1108
|
+
}
|
|
1109
|
+
break;
|
|
1110
|
+
case "le-button":
|
|
1111
|
+
if (!customElements.get(tagName)) {
|
|
1112
|
+
defineCustomElement();
|
|
1113
|
+
}
|
|
1114
|
+
break;
|
|
1115
|
+
case "le-checkbox":
|
|
1116
|
+
if (!customElements.get(tagName)) {
|
|
1117
|
+
defineCustomElement$1();
|
|
1118
|
+
}
|
|
1119
|
+
break;
|
|
1120
|
+
case "le-component":
|
|
1121
|
+
if (!customElements.get(tagName)) {
|
|
1122
|
+
defineCustomElement$2();
|
|
1123
|
+
}
|
|
1124
|
+
break;
|
|
1125
|
+
case "le-popover":
|
|
1126
|
+
if (!customElements.get(tagName)) {
|
|
1127
|
+
defineCustomElement$5();
|
|
1128
|
+
}
|
|
1129
|
+
break;
|
|
1130
|
+
case "le-slot":
|
|
1131
|
+
if (!customElements.get(tagName)) {
|
|
1132
|
+
defineCustomElement$3();
|
|
1133
|
+
}
|
|
1134
|
+
break;
|
|
1135
|
+
case "le-string-input":
|
|
1136
|
+
if (!customElements.get(tagName)) {
|
|
1137
|
+
defineCustomElement$4();
|
|
1138
|
+
}
|
|
1139
|
+
break;
|
|
1140
|
+
} });
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
export { LeButton as L, defineCustomElement$3 as a, defineCustomElement$2 as b, defineCustomElement$1 as c, defineCustomElement$4 as d, defineCustomElement as e, LeCheckbox as f, LeComponent as g, LeSlot as h, LeStringInput as i };
|
|
1144
|
+
//# sourceMappingURL=le-button2.js.map
|
|
1197
1145
|
|
|
1198
|
-
|
|
1199
|
-
//# sourceMappingURL=le-button.le-checkbox.le-component.le-popover.le-slot.le-string-input.entry.js.map
|
|
1146
|
+
//# sourceMappingURL=le-button2.js.map
|