@lancar/lxui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/LICENSE +21 -0
  3. package/README.md +5072 -0
  4. package/css/base/reset.css +91 -0
  5. package/css/base/tokens-extended.css +119 -0
  6. package/css/base/tokens.css +105 -0
  7. package/css/base/typography.css +35 -0
  8. package/css/base/utils.css +26 -0
  9. package/css/components/accordion.css +25 -0
  10. package/css/components/alert.css +22 -0
  11. package/css/components/animations.css +26 -0
  12. package/css/components/avatar.css +38 -0
  13. package/css/components/back-top.css +32 -0
  14. package/css/components/badge.css +37 -0
  15. package/css/components/breadcrumb.css +13 -0
  16. package/css/components/button.css +103 -0
  17. package/css/components/callout.css +20 -0
  18. package/css/components/card.css +42 -0
  19. package/css/components/carousel.css +31 -0
  20. package/css/components/chip.css +52 -0
  21. package/css/components/code-block.css +22 -0
  22. package/css/components/collapse.css +6 -0
  23. package/css/components/compat.css +27 -0
  24. package/css/components/dark-mode.css +35 -0
  25. package/css/components/divider.css +36 -0
  26. package/css/components/dropdown.css +39 -0
  27. package/css/components/empty.css +34 -0
  28. package/css/components/fab.css +28 -0
  29. package/css/components/file-drop.css +47 -0
  30. package/css/components/forms.css +107 -0
  31. package/css/components/kbd.css +5 -0
  32. package/css/components/list-group.css +17 -0
  33. package/css/components/modal.css +50 -0
  34. package/css/components/nav.css +25 -0
  35. package/css/components/navbar.css +44 -0
  36. package/css/components/number-input.css +52 -0
  37. package/css/components/offcanvas.css +25 -0
  38. package/css/components/pagination.css +17 -0
  39. package/css/components/popover.css +12 -0
  40. package/css/components/progress.css +26 -0
  41. package/css/components/rating.css +28 -0
  42. package/css/components/section.css +18 -0
  43. package/css/components/skeleton.css +19 -0
  44. package/css/components/spinner.css +38 -0
  45. package/css/components/stat.css +58 -0
  46. package/css/components/steps.css +76 -0
  47. package/css/components/table.css +29 -0
  48. package/css/components/tag.css +29 -0
  49. package/css/components/timeline.css +11 -0
  50. package/css/components/toast.css +14 -0
  51. package/css/components/toggler.css +20 -0
  52. package/css/components/tooltip.css +10 -0
  53. package/css/index.css +59 -0
  54. package/css/layout/grid.css +71 -0
  55. package/css/layout/utilities.css +257 -0
  56. package/js/breakpoint.js +13 -0
  57. package/js/carousel.js +62 -0
  58. package/js/clipboard.js +28 -0
  59. package/js/collapse.js +36 -0
  60. package/js/counter.js +38 -0
  61. package/js/dropdown.js +27 -0
  62. package/js/index.js +19 -0
  63. package/js/init.js +89 -0
  64. package/js/modal.js +44 -0
  65. package/js/number-input.js +44 -0
  66. package/js/offcanvas.js +28 -0
  67. package/js/popover.js +39 -0
  68. package/js/rating.js +39 -0
  69. package/js/scrollspy.js +24 -0
  70. package/js/tab.js +18 -0
  71. package/js/theme.js +9 -0
  72. package/js/toast.js +73 -0
  73. package/js/tooltip.js +39 -0
  74. package/js/utils.js +20 -0
  75. package/lx-grid.min.css +2 -0
  76. package/lx-utilities.min.css +2 -0
  77. package/lxeditor.min.css +2 -0
  78. package/lxfonts.min.css +2 -0
  79. package/lxicons.min.css +2 -0
  80. package/lxmarked.js +276 -0
  81. package/lxthemes.min.css +2 -0
  82. package/lxui.bundle.js +540 -0
  83. package/lxui.bundle.min.js +13 -0
  84. package/lxui.css +2163 -0
  85. package/lxui.esm.js +669 -0
  86. package/lxui.esm.min.js +8 -0
  87. package/lxui.js +859 -0
  88. package/lxui.min.css +2 -0
  89. package/lxui.min.js +7 -0
  90. package/lxui.rtl.css +2466 -0
  91. package/lxui.rtl.min.css +2 -0
  92. package/marked.min.js +69 -0
  93. package/package.json +183 -0
  94. package/types/index.d.ts +284 -0
package/css/index.css ADDED
@@ -0,0 +1,59 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ /* LxUI — full bundle via @import */
3
+
4
+ /* Base */
5
+ @import '../css/base/reset.css';
6
+ @import '../css/base/tokens.css';
7
+ @import '../css/base/tokens-extended.css';
8
+ @import '../css/base/typography.css';
9
+ @import '../css/base/utils.css';
10
+
11
+ /* Layout */
12
+ @import '../css/layout/grid.css';
13
+ @import '../css/layout/utilities.css';
14
+
15
+ /* Components */
16
+ @import '../css/components/accordion.css';
17
+ @import '../css/components/alert.css';
18
+ @import '../css/components/animations.css';
19
+ @import '../css/components/avatar.css';
20
+ @import '../css/components/back-top.css';
21
+ @import '../css/components/badge.css';
22
+ @import '../css/components/breadcrumb.css';
23
+ @import '../css/components/button.css';
24
+ @import '../css/components/callout.css';
25
+ @import '../css/components/card.css';
26
+ @import '../css/components/carousel.css';
27
+ @import '../css/components/chip.css';
28
+ @import '../css/components/code-block.css';
29
+ @import '../css/components/collapse.css';
30
+ @import '../css/components/compat.css';
31
+ @import '../css/components/dark-mode.css';
32
+ @import '../css/components/divider.css';
33
+ @import '../css/components/dropdown.css';
34
+ @import '../css/components/empty.css';
35
+ @import '../css/components/fab.css';
36
+ @import '../css/components/file-drop.css';
37
+ @import '../css/components/forms.css';
38
+ @import '../css/components/kbd.css';
39
+ @import '../css/components/list-group.css';
40
+ @import '../css/components/modal.css';
41
+ @import '../css/components/nav.css';
42
+ @import '../css/components/navbar.css';
43
+ @import '../css/components/number-input.css';
44
+ @import '../css/components/offcanvas.css';
45
+ @import '../css/components/pagination.css';
46
+ @import '../css/components/popover.css';
47
+ @import '../css/components/progress.css';
48
+ @import '../css/components/rating.css';
49
+ @import '../css/components/section.css';
50
+ @import '../css/components/skeleton.css';
51
+ @import '../css/components/spinner.css';
52
+ @import '../css/components/stat.css';
53
+ @import '../css/components/steps.css';
54
+ @import '../css/components/table.css';
55
+ @import '../css/components/tag.css';
56
+ @import '../css/components/timeline.css';
57
+ @import '../css/components/toast.css';
58
+ @import '../css/components/toggler.css';
59
+ @import '../css/components/tooltip.css';
@@ -0,0 +1,71 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ /* grid */
3
+ * LxUI — lx-grid.min.css
4
+ * Grid system only (12-column CSS Grid)
5
+ * https://ui.lancar.id | cdn: https://cdn.lancar.id/ui/lx-grid.min.css
6
+ * ================================================================ */
7
+ :root{--lx-gap:1rem;--lx-container-padding-x:1rem;--lx-grid-cols:12}
8
+ .lx-container{width:100%;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
9
+ .lx-container-fluid{width:100%;padding-inline:var(--lx-container-padding-x)}
10
+ .lx-container-sm{max-width:640px;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
11
+ .lx-container-md{max-width:768px;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
12
+ .lx-container-lg{max-width:1024px;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
13
+ .lx-container-xl{max-width:1280px;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
14
+ .lx-container-2xl{max-width:1536px;margin-inline:auto;padding-inline:var(--lx-container-padding-x)}
15
+ @media(min-width:640px){.lx-container{max-width:640px}}
16
+ @media(min-width:768px){.lx-container{max-width:768px}:root{--lx-container-padding-x:1.5rem}}
17
+ @media(min-width:1024px){.lx-container{max-width:1024px}}
18
+ @media(min-width:1280px){.lx-container{max-width:1280px}}
19
+ @media(min-width:1536px){.lx-container{max-width:1536px}}
20
+ .lx-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--lx-gap)}
21
+ .lx-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}
22
+ .lx-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}
23
+ .lx-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}
24
+ .lx-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
25
+ .lx-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}
26
+ .lx-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}
27
+ .lx-cols-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}
28
+ .lx-col-1{grid-column:span 1/span 1}
29
+ .lx-col-2{grid-column:span 2/span 2}
30
+ .lx-col-3{grid-column:span 3/span 3}
31
+ .lx-col-4{grid-column:span 4/span 4}
32
+ .lx-col-5{grid-column:span 5/span 5}
33
+ .lx-col-6{grid-column:span 6/span 6}
34
+ .lx-col-7{grid-column:span 7/span 7}
35
+ .lx-col-8{grid-column:span 8/span 8}
36
+ .lx-col-9{grid-column:span 9/span 9}
37
+ .lx-col-10{grid-column:span 10/span 10}
38
+ .lx-col-11{grid-column:span 11/span 11}
39
+ .lx-col-12{grid-column:span 12/span 12}
40
+ .lx-col-offset-1{margin-inline-start:calc(100%/12*1)}
41
+ .lx-col-offset-2{margin-inline-start:calc(100%/12*2)}
42
+ .lx-col-offset-3{margin-inline-start:calc(100%/12*3)}
43
+ .lx-col-offset-4{margin-inline-start:calc(100%/12*4)}
44
+ .lx-col-offset-5{margin-inline-start:calc(100%/12*5)}
45
+ .lx-col-offset-6{margin-inline-start:calc(100%/12*6)}
46
+ .lx-order-first{order:-9999}.lx-order-last{order:9999}
47
+ .lx-order-1{order:1}.lx-order-2{order:2}.lx-order-3{order:3}
48
+ .lx-order-4{order:4}.lx-order-5{order:5}.lx-order-6{order:6}
49
+ .lx-gap-0{gap:0}.lx-gap-1{gap:.25rem}.lx-gap-2{gap:.5rem}
50
+ .lx-gap-3{gap:.75rem}.lx-gap-4{gap:1rem}.lx-gap-5{gap:1.25rem}
51
+ .lx-gap-6{gap:1.5rem}.lx-gap-8{gap:2rem}.lx-gap-10{gap:2.5rem}.lx-gap-12{gap:3rem}
52
+ .lx-gap-x-0{column-gap:0}.lx-gap-x-2{column-gap:.5rem}.lx-gap-x-4{column-gap:1rem}.lx-gap-x-6{column-gap:1.5rem}.lx-gap-x-8{column-gap:2rem}
53
+ .lx-gap-y-0{row-gap:0}.lx-gap-y-2{row-gap:.5rem}.lx-gap-y-4{row-gap:1rem}.lx-gap-y-6{row-gap:1.5rem}.lx-gap-y-8{row-gap:2rem}
54
+ @media(min-width:640px){
55
+ .lx-sm-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lx-sm-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lx-sm-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lx-sm-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
56
+ .lx-sm-col-1{grid-column:span 1/span 1}.lx-sm-col-2{grid-column:span 2/span 2}.lx-sm-col-3{grid-column:span 3/span 3}.lx-sm-col-4{grid-column:span 4/span 4}.lx-sm-col-6{grid-column:span 6/span 6}.lx-sm-col-12{grid-column:span 12/span 12}
57
+ .lx-sm-gap-2{gap:.5rem}.lx-sm-gap-4{gap:1rem}.lx-sm-gap-6{gap:1.5rem}}
58
+ @media(min-width:768px){
59
+ .lx-md-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lx-md-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lx-md-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lx-md-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lx-md-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}
60
+ .lx-md-col-1{grid-column:span 1/span 1}.lx-md-col-2{grid-column:span 2/span 2}.lx-md-col-3{grid-column:span 3/span 3}.lx-md-col-4{grid-column:span 4/span 4}.lx-md-col-5{grid-column:span 5/span 5}.lx-md-col-6{grid-column:span 6/span 6}.lx-md-col-7{grid-column:span 7/span 7}.lx-md-col-8{grid-column:span 8/span 8}.lx-md-col-9{grid-column:span 9/span 9}.lx-md-col-10{grid-column:span 10/span 10}.lx-md-col-12{grid-column:span 12/span 12}
61
+ .lx-md-col-offset-3{margin-inline-start:25%}.lx-md-col-offset-4{margin-inline-start:33.333%}
62
+ .lx-md-gap-2{gap:.5rem}.lx-md-gap-4{gap:1rem}.lx-md-gap-6{gap:1.5rem}.lx-md-gap-8{gap:2rem}}
63
+ @media(min-width:1024px){
64
+ .lx-lg-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lx-lg-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lx-lg-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lx-lg-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lx-lg-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lx-lg-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}
65
+ .lx-lg-col-1{grid-column:span 1/span 1}.lx-lg-col-2{grid-column:span 2/span 2}.lx-lg-col-3{grid-column:span 3/span 3}.lx-lg-col-4{grid-column:span 4/span 4}.lx-lg-col-5{grid-column:span 5/span 5}.lx-lg-col-6{grid-column:span 6/span 6}.lx-lg-col-8{grid-column:span 8/span 8}.lx-lg-col-9{grid-column:span 9/span 9}.lx-lg-col-12{grid-column:span 12/span 12}
66
+ .lx-lg-gap-4{gap:1rem}.lx-lg-gap-6{gap:1.5rem}.lx-lg-gap-8{gap:2rem}}
67
+ @media(min-width:1280px){
68
+ .lx-xl-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lx-xl-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lx-xl-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
69
+ .lx-xl-col-3{grid-column:span 3/span 3}.lx-xl-col-4{grid-column:span 4/span 4}.lx-xl-col-6{grid-column:span 6/span 6}}
70
+
71
+ /* ================================================================
@@ -0,0 +1,257 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ /* utilities */
3
+ * LxUI — lx-utilities.min.css
4
+ * Utility classes only (display, spacing, flex, text, color, etc.)
5
+ * https://ui.lancar.id | cdn: https://cdn.lancar.id/ui/lx-utilities.min.css
6
+ * ================================================================ */
7
+
8
+ /* Display */
9
+ .lx-block{display:block}.lx-inline{display:inline}.lx-inline-block{display:inline-block}
10
+ .lx-flex{display:flex}.lx-inline-flex{display:inline-flex}.lx-grid{display:grid}.lx-inline-grid{display:inline-grid}
11
+ .lx-table{display:table}.lx-table-row{display:table-row}.lx-table-cell{display:table-cell}
12
+ .lx-contents{display:contents}.lx-hidden{display:none}
13
+ @media print{.lx-print-hidden{display:none!important}.lx-print-block{display:block!important}}
14
+
15
+ /* Flex */
16
+ .lx-flex-row{flex-direction:row}.lx-flex-row-reverse{flex-direction:row-reverse}
17
+ .lx-flex-col{flex-direction:column}.lx-flex-col-reverse{flex-direction:column-reverse}
18
+ .lx-flex-wrap{flex-wrap:wrap}.lx-flex-nowrap{flex-wrap:nowrap}.lx-flex-wrap-reverse{flex-wrap:wrap-reverse}
19
+ .lx-justify-start{justify-content:flex-start}.lx-justify-end{justify-content:flex-end}
20
+ .lx-justify-center{justify-content:center}.lx-justify-between{justify-content:space-between}
21
+ .lx-justify-around{justify-content:space-around}.lx-justify-evenly{justify-content:space-evenly}
22
+ .lx-items-start{align-items:flex-start}.lx-items-end{align-items:flex-end}
23
+ .lx-items-center{align-items:center}.lx-items-baseline{align-items:baseline}.lx-items-stretch{align-items:stretch}
24
+ .lx-self-start{align-self:flex-start}.lx-self-end{align-self:flex-end}
25
+ .lx-self-center{align-self:center}.lx-self-stretch{align-self:stretch}.lx-self-auto{align-self:auto}
26
+ .lx-content-start{align-content:flex-start}.lx-content-end{align-content:flex-end}
27
+ .lx-content-center{align-content:center}.lx-content-between{align-content:space-between}
28
+ .lx-flex-1{flex:1 1 0%}.lx-flex-auto{flex:1 1 auto}.lx-flex-none{flex:none}
29
+ .lx-flex-shrink-0{flex-shrink:0}.lx-flex-shrink{flex-shrink:1}
30
+ .lx-grow{flex-grow:1}.lx-grow-0{flex-grow:0}
31
+
32
+ /* Stack layouts */
33
+ .lx-stack>*+*{margin-block-start:var(--lx-stack-gap,1rem)}
34
+ .lx-hstack{display:flex;align-items:center}
35
+
36
+ /* Spacing — Margin */
37
+ .lx-m-0{margin:0}.lx-m-1{margin:.25rem}.lx-m-2{margin:.5rem}.lx-m-3{margin:.75rem}
38
+ .lx-m-4{margin:1rem}.lx-m-5{margin:1.25rem}.lx-m-6{margin:1.5rem}.lx-m-8{margin:2rem}
39
+ .lx-m-10{margin:2.5rem}.lx-m-12{margin:3rem}.lx-m-16{margin:4rem}.lx-m-auto{margin:auto}
40
+ .lx-mt-0{margin-top:0}.lx-mt-1{margin-top:.25rem}.lx-mt-2{margin-top:.5rem}.lx-mt-3{margin-top:.75rem}.lx-mt-4{margin-top:1rem}.lx-mt-5{margin-top:1.25rem}.lx-mt-6{margin-top:1.5rem}.lx-mt-8{margin-top:2rem}.lx-mt-10{margin-top:2.5rem}.lx-mt-12{margin-top:3rem}.lx-mt-16{margin-top:4rem}.lx-mt-auto{margin-top:auto}
41
+ .lx-mb-0{margin-bottom:0}.lx-mb-1{margin-bottom:.25rem}.lx-mb-2{margin-bottom:.5rem}.lx-mb-3{margin-bottom:.75rem}.lx-mb-4{margin-bottom:1rem}.lx-mb-5{margin-bottom:1.25rem}.lx-mb-6{margin-bottom:1.5rem}.lx-mb-8{margin-bottom:2rem}.lx-mb-10{margin-bottom:2.5rem}.lx-mb-12{margin-bottom:3rem}.lx-mb-16{margin-bottom:4rem}.lx-mb-auto{margin-bottom:auto}
42
+ .lx-ms-0{margin-inline-start:0}.lx-ms-1{margin-inline-start:.25rem}.lx-ms-2{margin-inline-start:.5rem}.lx-ms-3{margin-inline-start:.75rem}.lx-ms-4{margin-inline-start:1rem}.lx-ms-5{margin-inline-start:1.25rem}.lx-ms-6{margin-inline-start:1.5rem}.lx-ms-8{margin-inline-start:2rem}.lx-ms-auto{margin-inline-start:auto}
43
+ .lx-me-0{margin-inline-end:0}.lx-me-1{margin-inline-end:.25rem}.lx-me-2{margin-inline-end:.5rem}.lx-me-3{margin-inline-end:.75rem}.lx-me-4{margin-inline-end:1rem}.lx-me-5{margin-inline-end:1.25rem}.lx-me-6{margin-inline-end:1.5rem}.lx-me-8{margin-inline-end:2rem}.lx-me-auto{margin-inline-end:auto}
44
+ .lx-mx-0{margin-inline:0}.lx-mx-1{margin-inline:.25rem}.lx-mx-2{margin-inline:.5rem}.lx-mx-3{margin-inline:.75rem}.lx-mx-4{margin-inline:1rem}.lx-mx-6{margin-inline:1.5rem}.lx-mx-8{margin-inline:2rem}.lx-mx-auto{margin-inline:auto}
45
+ .lx-my-0{margin-block:0}.lx-my-1{margin-block:.25rem}.lx-my-2{margin-block:.5rem}.lx-my-3{margin-block:.75rem}.lx-my-4{margin-block:1rem}.lx-my-6{margin-block:1.5rem}.lx-my-8{margin-block:2rem}.lx-my-auto{margin-block:auto}
46
+
47
+ /* Spacing — Padding */
48
+ .lx-p-0{padding:0}.lx-p-1{padding:.25rem}.lx-p-2{padding:.5rem}.lx-p-3{padding:.75rem}
49
+ .lx-p-4{padding:1rem}.lx-p-5{padding:1.25rem}.lx-p-6{padding:1.5rem}.lx-p-8{padding:2rem}
50
+ .lx-p-10{padding:2.5rem}.lx-p-12{padding:3rem}.lx-p-16{padding:4rem}
51
+ .lx-pt-0{padding-top:0}.lx-pt-1{padding-top:.25rem}.lx-pt-2{padding-top:.5rem}.lx-pt-3{padding-top:.75rem}.lx-pt-4{padding-top:1rem}.lx-pt-6{padding-top:1.5rem}.lx-pt-8{padding-top:2rem}.lx-pt-12{padding-top:3rem}.lx-pt-16{padding-top:4rem}
52
+ .lx-pb-0{padding-bottom:0}.lx-pb-1{padding-bottom:.25rem}.lx-pb-2{padding-bottom:.5rem}.lx-pb-3{padding-bottom:.75rem}.lx-pb-4{padding-bottom:1rem}.lx-pb-6{padding-bottom:1.5rem}.lx-pb-8{padding-bottom:2rem}.lx-pb-12{padding-bottom:3rem}.lx-pb-16{padding-bottom:4rem}
53
+ .lx-ps-0{padding-inline-start:0}.lx-ps-1{padding-inline-start:.25rem}.lx-ps-2{padding-inline-start:.5rem}.lx-ps-3{padding-inline-start:.75rem}.lx-ps-4{padding-inline-start:1rem}.lx-ps-5{padding-inline-start:1.25rem}.lx-ps-6{padding-inline-start:1.5rem}.lx-ps-8{padding-inline-start:2rem}
54
+ .lx-pe-0{padding-inline-end:0}.lx-pe-1{padding-inline-end:.25rem}.lx-pe-2{padding-inline-end:.5rem}.lx-pe-3{padding-inline-end:.75rem}.lx-pe-4{padding-inline-end:1rem}.lx-pe-5{padding-inline-end:1.25rem}.lx-pe-6{padding-inline-end:1.5rem}.lx-pe-8{padding-inline-end:2rem}
55
+ .lx-px-0{padding-inline:0}.lx-px-1{padding-inline:.25rem}.lx-px-2{padding-inline:.5rem}.lx-px-3{padding-inline:.75rem}.lx-px-4{padding-inline:1rem}.lx-px-5{padding-inline:1.25rem}.lx-px-6{padding-inline:1.5rem}.lx-px-8{padding-inline:2rem}
56
+ .lx-py-0{padding-block:0}.lx-py-1{padding-block:.25rem}.lx-py-2{padding-block:.5rem}.lx-py-3{padding-block:.75rem}.lx-py-4{padding-block:1rem}.lx-py-5{padding-block:1.25rem}.lx-py-6{padding-block:1.5rem}.lx-py-8{padding-block:2rem}
57
+
58
+ /* Text */
59
+ .lx-text-xs{font-size:.75rem}.lx-text-sm{font-size:.875rem}.lx-text-base{font-size:1rem}
60
+ .lx-text-lg{font-size:1.125rem}.lx-text-xl{font-size:1.25rem}.lx-text-2xl{font-size:1.5rem}
61
+ .lx-text-3xl{font-size:1.875rem}.lx-text-4xl{font-size:2.25rem}.lx-text-5xl{font-size:3rem}
62
+ .lx-text-left{text-align:left}.lx-text-center{text-align:center}.lx-text-right{text-align:right}
63
+ .lx-text-justify{text-align:justify}.lx-text-start{text-align:start}.lx-text-end{text-align:end}
64
+ .lx-font-thin{font-weight:100}.lx-font-extralight{font-weight:200}.lx-font-light{font-weight:300}
65
+ .lx-font-normal{font-weight:400}.lx-font-medium{font-weight:500}.lx-font-semibold{font-weight:600}
66
+ .lx-font-bold{font-weight:700}.lx-font-extrabold{font-weight:800}.lx-font-black{font-weight:900}
67
+ .lx-italic{font-style:italic}.lx-not-italic{font-style:normal}
68
+ .lx-uppercase{text-transform:uppercase}.lx-lowercase{text-transform:lowercase}
69
+ .lx-capitalize{text-transform:capitalize}.lx-normal-case{text-transform:none}
70
+ .lx-underline{text-decoration-line:underline}.lx-overline{text-decoration-line:overline}
71
+ .lx-line-through{text-decoration-line:line-through}.lx-no-underline{text-decoration:none}
72
+ .lx-tracking-tighter{letter-spacing:-.05em}.lx-tracking-tight{letter-spacing:-.025em}
73
+ .lx-tracking-normal{letter-spacing:0}.lx-tracking-wide{letter-spacing:.025em}
74
+ .lx-tracking-wider{letter-spacing:.05em}.lx-tracking-widest{letter-spacing:.1em}
75
+ .lx-leading-none{line-height:1}.lx-leading-tight{line-height:1.25}.lx-leading-snug{line-height:1.375}
76
+ .lx-leading-normal{line-height:1.6}.lx-leading-relaxed{line-height:1.75}.lx-leading-loose{line-height:2}
77
+ .lx-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
78
+ .lx-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
79
+ .lx-line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}
80
+ .lx-line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}
81
+ .lx-line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}
82
+ .lx-line-clamp-4{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}
83
+ .lx-whitespace-nowrap{white-space:nowrap}.lx-whitespace-pre{white-space:pre}
84
+ .lx-whitespace-pre-wrap{white-space:pre-wrap}.lx-whitespace-normal{white-space:normal}
85
+ .lx-break-all{word-break:break-all}.lx-break-words{overflow-wrap:break-word}
86
+ .lx-word-break{word-break:break-all}
87
+
88
+ /* Colors */
89
+ .lx-text-primary{color:var(--lx-primary,#3b82f6)}.lx-text-secondary{color:var(--lx-secondary,#6b7280)}
90
+ .lx-text-success{color:var(--lx-success,#22c55e)}.lx-text-warning{color:var(--lx-warning,#f59e0b)}
91
+ .lx-text-danger{color:var(--lx-danger,#ef4444)}.lx-text-info{color:var(--lx-info,#06b6d4)}
92
+ .lx-text-dark{color:var(--lx-dark,#1f2937)}.lx-text-light{color:var(--lx-light,#f9fafb)}
93
+ .lx-text-white{color:#fff}.lx-text-black{color:#000}
94
+ .lx-text-muted{color:var(--text-muted,#9ca3af)}.lx-text-body{color:var(--text-primary,#111827)}
95
+ .lx-text-opacity-75{opacity:.75}.lx-text-opacity-50{opacity:.5}.lx-text-opacity-25{opacity:.25}
96
+ .lx-bg-primary{background-color:var(--lx-primary,#3b82f6)}.lx-bg-secondary{background-color:var(--lx-secondary,#6b7280)}
97
+ .lx-bg-success{background-color:var(--lx-success,#22c55e)}.lx-bg-warning{background-color:var(--lx-warning,#f59e0b)}
98
+ .lx-bg-danger{background-color:var(--lx-danger,#ef4444)}.lx-bg-info{background-color:var(--lx-info,#06b6d4)}
99
+ .lx-bg-dark{background-color:var(--lx-dark,#1f2937)}.lx-bg-light{background-color:var(--lx-light,#f9fafb)}
100
+ .lx-bg-white{background-color:#fff}.lx-bg-transparent{background-color:transparent}
101
+ .lx-bg-primary-soft{background-color:color-mix(in srgb,var(--lx-primary,#3b82f6) 12%,white)}
102
+ .lx-bg-success-soft{background-color:color-mix(in srgb,var(--lx-success,#22c55e) 12%,white)}
103
+ .lx-bg-warning-soft{background-color:color-mix(in srgb,var(--lx-warning,#f59e0b) 12%,white)}
104
+ .lx-bg-danger-soft{background-color:color-mix(in srgb,var(--lx-danger,#ef4444) 12%,white)}
105
+ .lx-bg-opacity-75{opacity:.75}.lx-bg-opacity-50{opacity:.5}.lx-bg-opacity-25{opacity:.25}.lx-bg-opacity-10{opacity:.1}
106
+
107
+ /* Sizing */
108
+ .lx-w-auto{width:auto}.lx-w-full{width:100%}.lx-w-screen{width:100vw}.lx-w-fit{width:fit-content}
109
+ .lx-w-1\/2{width:50%}.lx-w-1\/3{width:33.333%}.lx-w-2\/3{width:66.666%}
110
+ .lx-w-1\/4{width:25%}.lx-w-3\/4{width:75%}.lx-w-1\/5{width:20%}.lx-w-4\/5{width:80%}
111
+ .lx-w-4{width:1rem}.lx-w-6{width:1.5rem}.lx-w-8{width:2rem}.lx-w-12{width:3rem}.lx-w-16{width:4rem}.lx-w-24{width:6rem}.lx-w-32{width:8rem}.lx-w-48{width:12rem}.lx-w-64{width:16rem}
112
+ .lx-h-auto{height:auto}.lx-h-full{height:100%}.lx-h-screen{height:100vh}.lx-h-fit{height:fit-content}
113
+ .lx-h-4{height:1rem}.lx-h-6{height:1.5rem}.lx-h-8{height:2rem}.lx-h-12{height:3rem}.lx-h-16{height:4rem}.lx-h-24{height:6rem}.lx-h-32{height:8rem}
114
+ .lx-min-w-0{min-width:0}.lx-max-w-full{max-width:100%}.lx-max-w-screen-sm{max-width:640px}.lx-max-w-screen-md{max-width:768px}.lx-max-w-screen-lg{max-width:1024px}.lx-max-w-screen-xl{max-width:1280px}
115
+ .lx-min-h-screen{min-height:100vh}.lx-max-h-screen{max-height:100vh}.lx-max-h-64{max-height:16rem}
116
+ .lx-size-4{width:1rem;height:1rem}.lx-size-6{width:1.5rem;height:1.5rem}.lx-size-8{width:2rem;height:2rem}.lx-size-12{width:3rem;height:3rem}.lx-size-16{width:4rem;height:4rem}
117
+
118
+ /* Position */
119
+ .lx-static{position:static}.lx-relative{position:relative}.lx-absolute{position:absolute}
120
+ .lx-fixed{position:fixed}.lx-sticky{position:sticky}
121
+ .lx-top-0{top:0}.lx-top-50{top:50%}.lx-top-100{top:100%}.lx-top-auto{top:auto}
122
+ .lx-bottom-0{bottom:0}.lx-bottom-50{bottom:50%}.lx-bottom-auto{bottom:auto}
123
+ .lx-start-0{inset-inline-start:0}.lx-start-50{inset-inline-start:50%}.lx-start-auto{inset-inline-start:auto}
124
+ .lx-end-0{inset-inline-end:0}.lx-end-50{inset-inline-end:50%}.lx-end-auto{inset-inline-end:auto}
125
+ .lx-inset-0{inset:0}
126
+ .lx-translate-middle{transform:translate(-50%,-50%)}
127
+ .lx-translate-middle-x{transform:translateX(-50%)}
128
+ .lx-translate-middle-y{transform:translateY(-50%)}
129
+ .lx-sticky-top{position:sticky;top:0;z-index:var(--lx-z-sticky,1020)}
130
+
131
+ /* Border */
132
+ .lx-border{border:1px solid var(--border-default,#e5e7eb)}
133
+ .lx-border-0{border:0!important}.lx-border-2{border-width:2px}.lx-border-3{border-width:3px}
134
+ .lx-border-t{border-top:1px solid var(--border-default,#e5e7eb)}
135
+ .lx-border-b{border-bottom:1px solid var(--border-default,#e5e7eb)}
136
+ .lx-border-s{border-inline-start:1px solid var(--border-default,#e5e7eb)}
137
+ .lx-border-e{border-inline-end:1px solid var(--border-default,#e5e7eb)}
138
+ .lx-border-t-0{border-top:0}.lx-border-b-0{border-bottom:0}
139
+ .lx-border-primary{border-color:var(--lx-primary,#3b82f6)!important}
140
+ .lx-border-success{border-color:var(--lx-success,#22c55e)!important}
141
+ .lx-border-danger{border-color:var(--lx-danger,#ef4444)!important}
142
+ .lx-border-warning{border-color:var(--lx-warning,#f59e0b)!important}
143
+ .lx-border-white{border-color:#fff!important}
144
+ .lx-border-opacity-50{border-color:color-mix(in srgb,currentColor 50%,transparent)!important}
145
+ .lx-rounded-none{border-radius:0}.lx-rounded-sm{border-radius:4px}.lx-rounded{border-radius:8px}
146
+ .lx-rounded-md{border-radius:12px}.lx-rounded-lg{border-radius:16px}.lx-rounded-xl{border-radius:24px}
147
+ .lx-rounded-2xl{border-radius:32px}.lx-rounded-full{border-radius:9999px}
148
+ .lx-rounded-t{border-top-left-radius:8px;border-top-right-radius:8px}
149
+ .lx-rounded-b{border-bottom-left-radius:8px;border-bottom-right-radius:8px}
150
+ .lx-rounded-s{border-top-left-radius:8px;border-bottom-left-radius:8px}
151
+ .lx-rounded-e{border-top-right-radius:8px;border-bottom-right-radius:8px}
152
+
153
+ /* Shadow */
154
+ .lx-shadow-none{box-shadow:none!important}
155
+ .lx-shadow-xs{box-shadow:0 1px 2px rgba(0,0,0,.04)}
156
+ .lx-shadow-sm{box-shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04)}
157
+ .lx-shadow{box-shadow:0 4px 6px -1px rgba(0,0,0,.07),0 2px 4px -2px rgba(0,0,0,.05)}
158
+ .lx-shadow-md{box-shadow:0 8px 12px -3px rgba(0,0,0,.08),0 4px 6px -4px rgba(0,0,0,.05)}
159
+ .lx-shadow-lg{box-shadow:0 16px 24px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.05)}
160
+ .lx-shadow-xl{box-shadow:0 24px 40px -8px rgba(0,0,0,.12),0 12px 16px -8px rgba(0,0,0,.06)}
161
+ .lx-shadow-2xl{box-shadow:0 40px 60px -12px rgba(0,0,0,.18)}
162
+ .lx-shadow-inner{box-shadow:inset 0 2px 4px rgba(0,0,0,.06)}
163
+
164
+ /* Overflow */
165
+ .lx-overflow-auto{overflow:auto}.lx-overflow-hidden{overflow:hidden}
166
+ .lx-overflow-visible{overflow:visible}.lx-overflow-scroll{overflow:scroll}
167
+ .lx-overflow-x-auto{overflow-x:auto}.lx-overflow-y-auto{overflow-y:auto}
168
+ .lx-overflow-x-hidden{overflow-x:hidden}.lx-overflow-y-hidden{overflow-y:hidden}
169
+ .lx-overflow-x-scroll{overflow-x:scroll}.lx-overflow-y-scroll{overflow-y:scroll}
170
+
171
+ /* Visibility */
172
+ .lx-visible{visibility:visible}.lx-invisible{visibility:hidden}
173
+ .lx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
174
+ .lx-sr-only-focusable:focus,.lx-sr-only-focusable:focus-within{position:static;width:auto;height:auto;padding:inherit;margin:inherit;overflow:visible;clip:auto;white-space:normal}
175
+
176
+ /* Interactions */
177
+ .lx-pointer-events-none{pointer-events:none}.lx-pointer-events-auto{pointer-events:auto}
178
+ .lx-select-none{user-select:none}.lx-select-all{user-select:all}.lx-select-text{user-select:text}
179
+ .lx-cursor-pointer{cursor:pointer}.lx-cursor-default{cursor:default}.lx-cursor-auto{cursor:auto}
180
+ .lx-cursor-not-allowed{cursor:not-allowed}.lx-cursor-wait{cursor:wait}
181
+ .lx-cursor-move{cursor:move}.lx-cursor-grab{cursor:grab}.lx-cursor-text{cursor:text}
182
+
183
+ /* Float */
184
+ .lx-float-start{float:inline-start}.lx-float-end{float:inline-end}.lx-float-none{float:none}
185
+ .lx-clearfix::after{content:"";display:table;clear:both}
186
+
187
+ /* Vertical align */
188
+ .lx-align-baseline{vertical-align:baseline}.lx-align-top{vertical-align:top}
189
+ .lx-align-middle{vertical-align:middle}.lx-align-bottom{vertical-align:bottom}
190
+ .lx-align-text-top{vertical-align:text-top}.lx-align-text-bottom{vertical-align:text-bottom}
191
+ .lx-align-sub{vertical-align:sub}.lx-align-super{vertical-align:super}
192
+
193
+ /* Object fit */
194
+ .lx-object-cover{object-fit:cover}.lx-object-contain{object-fit:contain}
195
+ .lx-object-fill{object-fit:fill}.lx-object-none{object-fit:none}
196
+ .lx-object-center{object-position:center}.lx-object-top{object-position:top}
197
+
198
+ /* Opacity */
199
+ .lx-opacity-0{opacity:0}.lx-opacity-25{opacity:.25}.lx-opacity-50{opacity:.5}
200
+ .lx-opacity-75{opacity:.75}.lx-opacity-100{opacity:1}
201
+
202
+ /* Text opacity helpers */
203
+ .lx-text-opacity-75{color:color-mix(in srgb,currentColor 75%,transparent)!important}
204
+ .lx-text-opacity-50{color:color-mix(in srgb,currentColor 50%,transparent)!important}
205
+ .lx-text-opacity-25{color:color-mix(in srgb,currentColor 25%,transparent)!important}
206
+ .lx-text-opacity-80{color:color-mix(in srgb,currentColor 80%,transparent)!important}
207
+
208
+ /* Z-index */
209
+ .lx-z-n1{z-index:-1}.lx-z-0{z-index:0}.lx-z-10{z-index:10}.lx-z-20{z-index:20}.lx-z-50{z-index:50}
210
+ .lx-z-dropdown{z-index:1000}.lx-z-sticky{z-index:1020}.lx-z-fixed{z-index:1030}
211
+ .lx-z-offcanvas{z-index:1040}.lx-z-modal-bg{z-index:1050}.lx-z-modal{z-index:1060}
212
+ .lx-z-popover{z-index:1070}.lx-z-tooltip{z-index:1080}.lx-z-toast{z-index:1090}
213
+
214
+ /* Ratio */
215
+ .lx-ratio{position:relative;width:100%}
216
+ .lx-ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}
217
+ .lx-ratio::before{display:block;content:"";padding-top:calc(var(--lx-aspect-ratio) * 100%)}
218
+ .lx-ratio-1x1{--lx-aspect-ratio:1}.lx-ratio-4x3{--lx-aspect-ratio:calc(3/4)}
219
+ .lx-ratio-16x9{--lx-aspect-ratio:calc(9/16)}.lx-ratio-21x9{--lx-aspect-ratio:calc(9/21)}
220
+
221
+ /* Stretched link */
222
+ .lx-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}
223
+
224
+ /* Responsive utilities */
225
+ @media(min-width:640px){
226
+ .lx-sm-block{display:block}.lx-sm-flex{display:flex}.lx-sm-grid{display:grid}.lx-sm-hidden{display:none}
227
+ .lx-sm-text-center{text-align:center}.lx-sm-text-left{text-align:left}
228
+ .lx-sm-w-full{width:100%}.lx-sm-w-auto{width:auto}}
229
+ @media(min-width:768px){
230
+ .lx-md-block{display:block}.lx-md-flex{display:flex}.lx-md-grid{display:grid}.lx-md-hidden{display:none}
231
+ .lx-md-inline-flex{display:inline-flex}.lx-md-inline-block{display:inline-block}
232
+ .lx-md-flex-row{flex-direction:row}.lx-md-flex-col{flex-direction:column}
233
+ .lx-md-justify-center{justify-content:center}.lx-md-justify-between{justify-content:space-between}
234
+ .lx-md-items-center{align-items:center}.lx-md-items-start{align-items:flex-start}
235
+ .lx-md-text-center{text-align:center}.lx-md-text-left{text-align:left}.lx-md-text-right{text-align:right}
236
+ .lx-md-text-sm{font-size:.875rem}.lx-md-text-base{font-size:1rem}.lx-md-text-lg{font-size:1.125rem}.lx-md-text-xl{font-size:1.25rem}.lx-md-text-2xl{font-size:1.5rem}.lx-md-text-3xl{font-size:1.875rem}
237
+ .lx-md-p-0{padding:0}.lx-md-p-2{padding:.5rem}.lx-md-p-4{padding:1rem}.lx-md-p-6{padding:1.5rem}.lx-md-p-8{padding:2rem}
238
+ .lx-md-px-4{padding-inline:1rem}.lx-md-px-6{padding-inline:1.5rem}.lx-md-px-8{padding-inline:2rem}
239
+ .lx-md-py-4{padding-block:1rem}.lx-md-py-6{padding-block:1.5rem}.lx-md-py-8{padding-block:2rem}
240
+ .lx-md-mt-0{margin-top:0}.lx-md-mt-4{margin-top:1rem}.lx-md-mt-8{margin-top:2rem}
241
+ .lx-md-w-full{width:100%}.lx-md-w-auto{width:auto}.lx-md-w-1\/2{width:50%}
242
+ .lx-md-float-start{float:inline-start}.lx-md-float-end{float:inline-end}.lx-md-float-none{float:none}}
243
+ @media(min-width:1024px){
244
+ .lx-lg-block{display:block}.lx-lg-flex{display:flex}.lx-lg-grid{display:grid}.lx-lg-hidden{display:none}
245
+ .lx-lg-inline-flex{display:inline-flex}.lx-lg-inline-block{display:inline-block}
246
+ .lx-lg-flex-row{flex-direction:row}.lx-lg-flex-col{flex-direction:column}
247
+ .lx-lg-justify-center{justify-content:center}.lx-lg-justify-between{justify-content:space-between}
248
+ .lx-lg-items-center{align-items:center}
249
+ .lx-lg-text-base{font-size:1rem}.lx-lg-text-lg{font-size:1.125rem}.lx-lg-text-xl{font-size:1.25rem}.lx-lg-text-2xl{font-size:1.5rem}.lx-lg-text-3xl{font-size:1.875rem}.lx-lg-text-4xl{font-size:2.25rem}
250
+ .lx-lg-p-4{padding:1rem}.lx-lg-p-6{padding:1.5rem}.lx-lg-p-8{padding:2rem}.lx-lg-p-12{padding:3rem}
251
+ .lx-lg-px-6{padding-inline:1.5rem}.lx-lg-px-8{padding-inline:2rem}.lx-lg-px-12{padding-inline:3rem}
252
+ .lx-lg-py-4{padding-block:1rem}.lx-lg-py-6{padding-block:1.5rem}.lx-lg-py-8{padding-block:2rem}
253
+ .lx-lg-w-auto{width:auto}.lx-lg-w-full{width:100%}}
254
+ @media(min-width:1280px){
255
+ .lx-xl-block{display:block}.lx-xl-flex{display:flex}.lx-xl-grid{display:grid}.lx-xl-hidden{display:none}}
256
+
257
+ /* ================================================================
@@ -0,0 +1,13 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ export const breakpoint = {
3
+ _bp: { xs: 0, sm: 640, md: 768, lg: 1024, xl: 1280, '2xl': 1536 },
4
+ current() {
5
+ const w = window.innerWidth;
6
+ return Object.entries(this._bp).reverse().find(([, v]) => w >= v)?.[0] || 'xs';
7
+ },
8
+ on(bp, fn) {
9
+ const mq = window.matchMedia(`(min-width: ${this._bp[bp]}px)`);
10
+ mq.addEventListener('change', e => { if (e.matches) fn(); });
11
+ if (mq.matches) fn();
12
+ }
13
+ };
package/js/carousel.js ADDED
@@ -0,0 +1,62 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ import { qs, qsa, on, off, emit, trap } from './utils.js';
3
+
4
+ export class Carousel {
5
+ constructor(sel, opts = {}) {
6
+ this.el = typeof sel === 'string' ? qs(sel) : sel;
7
+ if (!this.el) return;
8
+ this.opts = Object.assign({ interval: 5000, pause: 'hover', wrap: true, touch: true }, opts);
9
+ this.inner = qs('.lx-carousel-inner', this.el);
10
+ this.items = qsa('.lx-carousel-item', this.el);
11
+ this.current = this.items.findIndex(i => i.classList.contains('lx-active'));
12
+ if (this.current < 0) { this.current = 0; if (this.items[0]) this.items[0].classList.add('lx-active'); }
13
+ this._timer = null;
14
+ this._sliding = false;
15
+ if (this.inner) this._applyTransform(this.current, false);
16
+ if (this.opts.interval) this.cycle();
17
+ if (this.opts.pause === 'hover') { on(this.el, 'mouseenter', () => this.pause()); on(this.el, 'mouseleave', () => this.cycle()); }
18
+ if (this.opts.touch) this._initTouch();
19
+ this._updateIndicators();
20
+ }
21
+ _applyTransform(idx, animate) {
22
+ if (!this.inner) return;
23
+ if (!animate) this.inner.style.transition = 'none';
24
+ this.inner.style.transform = 'translateX(-' + (idx * 100) + '%)';
25
+ if (!animate) { this.inner.getBoundingClientRect(); this.inner.style.transition = ''; }
26
+ }
27
+ _go(idx) {
28
+ const n = this.items.length;
29
+ if (!this.opts.wrap && (idx < 0 || idx >= n)) return;
30
+ if (this._sliding) return;
31
+ this._sliding = true;
32
+ this.current = ((idx % n) + n) % n;
33
+ this.items.forEach((item, i) => item.classList.toggle('lx-active', i === this.current));
34
+ if (this.inner) {
35
+ this._applyTransform(this.current, true);
36
+ this.inner.addEventListener('transitionend', () => { this._sliding = false; emit(this.el, 'carousel.slid'); }, { once: true });
37
+ setTimeout(() => { this._sliding = false; }, 400);
38
+ } else { this._sliding = false; }
39
+ this._updateIndicators();
40
+ emit(this.el, 'carousel.slide');
41
+ }
42
+ _updateIndicators() {
43
+ qsa('.lx-carousel-indicators button, .lx-carousel-indicators [data-lx-slide-to]', this.el).forEach((btn, i) => {
44
+ btn.classList.toggle('lx-active', i === this.current);
45
+ btn.setAttribute('aria-current', i === this.current ? 'true' : 'false');
46
+ });
47
+ }
48
+ next() { this._go(this.current + 1); }
49
+ prev() { this._go(this.current - 1); }
50
+ to(idx) { this._go(idx); }
51
+ cycle() { this.pause(); if (this.opts.interval) this._timer = setInterval(() => this.next(), this.opts.interval); }
52
+ pause() { clearInterval(this._timer); this._timer = null; }
53
+ _initTouch() {
54
+ let startX = 0, startY = 0;
55
+ on(this.el, 'touchstart', e => { startX = e.touches[0].clientX; startY = e.touches[0].clientY; }, { passive: true });
56
+ on(this.el, 'touchend', e => {
57
+ const dx = e.changedTouches[0].clientX - startX;
58
+ const dy = e.changedTouches[0].clientY - startY;
59
+ if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) dx > 0 ? this.prev() : this.next();
60
+ });
61
+ }
62
+ }
@@ -0,0 +1,28 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ import { qs, qsa, on, off, emit, trap } from './utils.js';
3
+
4
+ export const Clipboard = {
5
+ copy(text) {
6
+ if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
7
+ const el = document.createElement('textarea');
8
+ el.value = text;
9
+ el.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0';
10
+ document.body.appendChild(el);
11
+ el.focus(); el.select();
12
+ try { document.execCommand('copy'); } catch (e) {}
13
+ el.remove();
14
+ return Promise.resolve();
15
+ },
16
+ bind(sel, getText) {
17
+ qsa(sel).forEach(btn => {
18
+ on(btn, 'click', async () => {
19
+ const text = typeof getText === 'function' ? getText(btn) : (btn.dataset.lxCopy || btn.textContent);
20
+ await this.copy(text);
21
+ const orig = btn.textContent;
22
+ btn.textContent = btn.dataset.lxCopiedText || 'Copied!';
23
+ btn.classList.add('lx-copied');
24
+ setTimeout(() => { btn.textContent = orig; btn.classList.remove('lx-copied'); }, 2000);
25
+ });
26
+ });
27
+ }
28
+ };
package/js/collapse.js ADDED
@@ -0,0 +1,36 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ import { qs, qsa, on, off, emit, trap } from './utils.js';
3
+
4
+ export class Collapse {
5
+ constructor(sel) { this.el = typeof sel === 'string' ? qs(sel) : sel; }
6
+ show() {
7
+ if (!this.el) return;
8
+ emit(this.el, 'collapse.show');
9
+ this.el.style.height = '0px';
10
+ this.el.classList.add('lx-collapsing');
11
+ this.el.classList.remove('lx-collapse', 'lx-show');
12
+ const h = this.el.scrollHeight;
13
+ this.el.style.height = h + 'px';
14
+ this.el.addEventListener('transitionend', () => {
15
+ this.el.classList.remove('lx-collapsing');
16
+ this.el.classList.add('lx-collapse', 'lx-show');
17
+ this.el.style.height = '';
18
+ emit(this.el, 'collapse.shown');
19
+ }, { once: true });
20
+ }
21
+ hide() {
22
+ if (!this.el) return;
23
+ emit(this.el, 'collapse.hide');
24
+ this.el.style.height = this.el.scrollHeight + 'px';
25
+ this.el.classList.add('lx-collapsing');
26
+ this.el.classList.remove('lx-collapse', 'lx-show');
27
+ requestAnimationFrame(() => { this.el.style.height = '0px'; });
28
+ this.el.addEventListener('transitionend', () => {
29
+ this.el.classList.remove('lx-collapsing');
30
+ this.el.classList.add('lx-collapse');
31
+ this.el.style.height = '';
32
+ emit(this.el, 'collapse.hidden');
33
+ }, { once: true });
34
+ }
35
+ toggle() { this.el && this.el.classList.contains('lx-show') ? this.hide() : this.show(); }
36
+ }
package/js/counter.js ADDED
@@ -0,0 +1,38 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ import { qs, qsa, on, off, emit, trap } from './utils.js';
3
+
4
+ export class Counter {
5
+ constructor(el, opts = {}) {
6
+ this.el = typeof el === 'string' ? qs(el) : el;
7
+ if (!this.el) return;
8
+ this.opts = Object.assign({
9
+ start: 0, end: parseInt(this.el.dataset.lxEnd || this.el.textContent) || 0,
10
+ duration: parseInt(this.el.dataset.lxDuration) || 2000,
11
+ prefix: this.el.dataset.lxPrefix || '', suffix: this.el.dataset.lxSuffix || '',
12
+ decimals: parseInt(this.el.dataset.lxDecimals) || 0, easing: true
13
+ }, opts);
14
+ }
15
+ _ease(t) { return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }
16
+ _format(n) { return this.opts.prefix + n.toFixed(this.opts.decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',') + this.opts.suffix; }
17
+ start() {
18
+ const { start, end, duration, easing } = this.opts, range = end - start;
19
+ let startTime = null;
20
+ const step = ts => {
21
+ if (!startTime) startTime = ts;
22
+ const elapsed = Math.min(ts - startTime, duration);
23
+ const progress = easing ? this._ease(elapsed / duration) : elapsed / duration;
24
+ this.el.textContent = this._format(start + range * progress);
25
+ if (elapsed < duration) requestAnimationFrame(step);
26
+ else this.el.textContent = this._format(end);
27
+ };
28
+ requestAnimationFrame(step);
29
+ }
30
+ static observeAll(sel, opts) {
31
+ if ('IntersectionObserver' in window) {
32
+ const io = new IntersectionObserver(entries => {
33
+ entries.forEach(e => { if (e.isIntersecting) { new Counter(e.target, opts).start(); io.unobserve(e.target); } });
34
+ }, { threshold: .5 });
35
+ qsa(sel).forEach(el => io.observe(el));
36
+ } else { qsa(sel).forEach(el => new Counter(el, opts).start()); }
37
+ }
38
+ }
package/js/dropdown.js ADDED
@@ -0,0 +1,27 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ import { qs, qsa, on, off, emit, trap } from './utils.js';
3
+
4
+ export class Dropdown {
5
+ constructor(trigger) {
6
+ this.trigger = typeof trigger === 'string' ? qs(trigger) : trigger;
7
+ this.menu = this.trigger && this.trigger.nextElementSibling;
8
+ this._outside = e => { if (!this.trigger.closest('.lx-dropdown').contains(e.target)) this.hide(); };
9
+ }
10
+ show() {
11
+ if (!this.menu) return;
12
+ emit(this.trigger, 'dropdown.show');
13
+ this.menu.classList.add('lx-show');
14
+ this.trigger.setAttribute('aria-expanded', 'true');
15
+ setTimeout(() => on(document, 'click', this._outside), 0);
16
+ emit(this.trigger, 'dropdown.shown');
17
+ }
18
+ hide() {
19
+ if (!this.menu) return;
20
+ emit(this.trigger, 'dropdown.hide');
21
+ this.menu.classList.remove('lx-show');
22
+ this.trigger.setAttribute('aria-expanded', 'false');
23
+ off(document, 'click', this._outside);
24
+ emit(this.trigger, 'dropdown.hidden');
25
+ }
26
+ toggle() { this.menu && this.menu.classList.contains('lx-show') ? this.hide() : this.show(); }
27
+ }
package/js/index.js ADDED
@@ -0,0 +1,19 @@
1
+ /*! LxUI v1.0.0 | MIT License | https://ui.lancar.id */
2
+ export { qs, qsa, on, off, emit, trap } from './utils.js';
3
+ export { Modal } from './modal.js';
4
+ export { Toast } from './toast.js';
5
+ export { Collapse } from './collapse.js';
6
+ export { Dropdown } from './dropdown.js';
7
+ export { Offcanvas } from './offcanvas.js';
8
+ export { Tooltip } from './tooltip.js';
9
+ export { Popover } from './popover.js';
10
+ export { Tab } from './tab.js';
11
+ export { Carousel } from './carousel.js';
12
+ export { Scrollspy } from './scrollspy.js';
13
+ export { Clipboard } from './clipboard.js';
14
+ export { Counter } from './counter.js';
15
+ export { NumberInput } from './number-input.js';
16
+ export { Rating } from './rating.js';
17
+ export { theme } from './theme.js';
18
+ export { breakpoint } from './breakpoint.js';
19
+ export { init } from './init.js';