@erplora/outfitkit 0.1.1

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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +457 -0
  3. package/dist/base/anchor.d.ts +13 -0
  4. package/dist/base/define.d.ts +1 -0
  5. package/dist/base/relay.d.ts +1 -0
  6. package/dist/cdn.d.ts +96 -0
  7. package/dist/components/ok-app-launcher/ok-app-launcher.d.ts +57 -0
  8. package/dist/components/ok-audio/ok-audio.d.ts +45 -0
  9. package/dist/components/ok-avatar/ok-avatar.d.ts +36 -0
  10. package/dist/components/ok-avatar-group/ok-avatar-group.d.ts +38 -0
  11. package/dist/components/ok-bar-list/ok-bar-list.d.ts +36 -0
  12. package/dist/components/ok-bento/ok-bento.d.ts +17 -0
  13. package/dist/components/ok-bento-item/ok-bento-item.d.ts +34 -0
  14. package/dist/components/ok-calculator/ok-calculator.d.ts +46 -0
  15. package/dist/components/ok-calendar/ok-calendar.d.ts +63 -0
  16. package/dist/components/ok-carousel/ok-carousel.d.ts +48 -0
  17. package/dist/components/ok-chart/ok-chart.d.ts +55 -0
  18. package/dist/components/ok-chat/ok-chat.d.ts +54 -0
  19. package/dist/components/ok-coachmark/ok-coachmark.d.ts +69 -0
  20. package/dist/components/ok-code/ok-code.d.ts +28 -0
  21. package/dist/components/ok-color-picker/ok-color-picker.d.ts +63 -0
  22. package/dist/components/ok-combo/ok-combo.d.ts +46 -0
  23. package/dist/components/ok-command-palette/ok-command-palette.d.ts +72 -0
  24. package/dist/components/ok-contact-form/ok-contact-form.d.ts +54 -0
  25. package/dist/components/ok-cropper/ok-cropper.d.ts +60 -0
  26. package/dist/components/ok-cta-band/ok-cta-band.d.ts +18 -0
  27. package/dist/components/ok-currency/ok-currency.d.ts +31 -0
  28. package/dist/components/ok-data-table/ok-data-table.d.ts +312 -0
  29. package/dist/components/ok-date-picker/ok-date-picker.d.ts +81 -0
  30. package/dist/components/ok-detail-list/ok-detail-list.d.ts +30 -0
  31. package/dist/components/ok-diff/ok-diff.d.ts +38 -0
  32. package/dist/components/ok-donut/ok-donut.d.ts +38 -0
  33. package/dist/components/ok-drawer/ok-drawer.d.ts +56 -0
  34. package/dist/components/ok-dropzone/ok-dropzone.d.ts +48 -0
  35. package/dist/components/ok-empty-state/ok-empty-state.d.ts +16 -0
  36. package/dist/components/ok-error-page/ok-error-page.d.ts +77 -0
  37. package/dist/components/ok-event-card/ok-event-card.d.ts +56 -0
  38. package/dist/components/ok-feature-card/ok-feature-card.d.ts +23 -0
  39. package/dist/components/ok-file-item/ok-file-item.d.ts +31 -0
  40. package/dist/components/ok-file-manager/ok-file-manager.d.ts +145 -0
  41. package/dist/components/ok-footer/ok-footer.d.ts +10 -0
  42. package/dist/components/ok-funnel/ok-funnel.d.ts +31 -0
  43. package/dist/components/ok-gallery/ok-gallery.d.ts +34 -0
  44. package/dist/components/ok-gauge/ok-gauge.d.ts +49 -0
  45. package/dist/components/ok-heatmap/ok-heatmap.d.ts +45 -0
  46. package/dist/components/ok-hero/ok-hero.d.ts +10 -0
  47. package/dist/components/ok-hover-card/ok-hover-card.d.ts +76 -0
  48. package/dist/components/ok-icon-tile/ok-icon-tile.d.ts +24 -0
  49. package/dist/components/ok-image/ok-image.d.ts +56 -0
  50. package/dist/components/ok-inline-feedback/ok-inline-feedback.d.ts +33 -0
  51. package/dist/components/ok-invoice/ok-invoice.d.ts +137 -0
  52. package/dist/components/ok-json-viewer/ok-json-viewer.d.ts +31 -0
  53. package/dist/components/ok-kanban/ok-kanban.d.ts +56 -0
  54. package/dist/components/ok-kbd/ok-kbd.d.ts +21 -0
  55. package/dist/components/ok-keyboard/ok-keyboard.d.ts +35 -0
  56. package/dist/components/ok-kpi/ok-kpi.d.ts +24 -0
  57. package/dist/components/ok-language-select/ok-language-select.d.ts +31 -0
  58. package/dist/components/ok-lightbox/ok-lightbox.d.ts +59 -0
  59. package/dist/components/ok-logo-cloud/ok-logo-cloud.d.ts +14 -0
  60. package/dist/components/ok-loyalty-card/ok-loyalty-card.d.ts +35 -0
  61. package/dist/components/ok-mail/ok-mail.d.ts +117 -0
  62. package/dist/components/ok-menu/ok-menu.d.ts +75 -0
  63. package/dist/components/ok-menubar/ok-menubar.d.ts +75 -0
  64. package/dist/components/ok-navbar/ok-navbar.d.ts +42 -0
  65. package/dist/components/ok-notification-center/ok-notification-center.d.ts +79 -0
  66. package/dist/components/ok-org-chart/ok-org-chart.d.ts +67 -0
  67. package/dist/components/ok-otp/ok-otp.d.ts +31 -0
  68. package/dist/components/ok-page-header/ok-page-header.d.ts +23 -0
  69. package/dist/components/ok-pagination/ok-pagination.d.ts +44 -0
  70. package/dist/components/ok-pdf/ok-pdf.d.ts +32 -0
  71. package/dist/components/ok-phone/ok-phone.d.ts +48 -0
  72. package/dist/components/ok-pinpad/ok-pinpad.d.ts +29 -0
  73. package/dist/components/ok-pricing-card/ok-pricing-card.d.ts +31 -0
  74. package/dist/components/ok-product-card/ok-product-card.d.ts +25 -0
  75. package/dist/components/ok-qr/ok-qr.d.ts +24 -0
  76. package/dist/components/ok-qty-stepper/ok-qty-stepper.d.ts +35 -0
  77. package/dist/components/ok-range-dual/ok-range-dual.d.ts +38 -0
  78. package/dist/components/ok-rating/ok-rating.d.ts +33 -0
  79. package/dist/components/ok-receipt/ok-receipt.d.ts +103 -0
  80. package/dist/components/ok-reveal/ok-reveal.d.ts +21 -0
  81. package/dist/components/ok-rich-text/ok-rich-text.d.ts +46 -0
  82. package/dist/components/ok-scheduler/ok-scheduler.d.ts +74 -0
  83. package/dist/components/ok-select-card/ok-select-card.d.ts +37 -0
  84. package/dist/components/ok-signature/ok-signature.d.ts +55 -0
  85. package/dist/components/ok-skeleton/ok-skeleton.d.ts +40 -0
  86. package/dist/components/ok-sparkline/ok-sparkline.d.ts +27 -0
  87. package/dist/components/ok-split-button/ok-split-button.d.ts +49 -0
  88. package/dist/components/ok-splitter/ok-splitter.d.ts +36 -0
  89. package/dist/components/ok-stat/ok-stat.d.ts +16 -0
  90. package/dist/components/ok-status-dot/ok-status-dot.d.ts +24 -0
  91. package/dist/components/ok-status-pill/ok-status-pill.d.ts +22 -0
  92. package/dist/components/ok-stepper/ok-stepper.d.ts +33 -0
  93. package/dist/components/ok-store/ok-store.d.ts +33 -0
  94. package/dist/components/ok-tag-input/ok-tag-input.d.ts +39 -0
  95. package/dist/components/ok-testimonial/ok-testimonial.d.ts +21 -0
  96. package/dist/components/ok-time-picker/ok-time-picker.d.ts +50 -0
  97. package/dist/components/ok-timeline/ok-timeline.d.ts +33 -0
  98. package/dist/components/ok-tree/ok-tree.d.ts +46 -0
  99. package/dist/components/ok-video/ok-video.d.ts +49 -0
  100. package/dist/components/ok-widget-board/ok-widget-board.d.ts +71 -0
  101. package/dist/components/ok-wizard/ok-wizard.d.ts +30 -0
  102. package/dist/define.js +8 -0
  103. package/dist/erplora.css +112 -0
  104. package/dist/index.d.ts +158 -0
  105. package/dist/index.js +197 -0
  106. package/dist/layout.css +338 -0
  107. package/dist/ok-app-launcher.js +396 -0
  108. package/dist/ok-audio.js +308 -0
  109. package/dist/ok-avatar-group.js +158 -0
  110. package/dist/ok-avatar.js +179 -0
  111. package/dist/ok-bar-list.js +189 -0
  112. package/dist/ok-bento-item.js +168 -0
  113. package/dist/ok-bento.js +63 -0
  114. package/dist/ok-calculator.js +406 -0
  115. package/dist/ok-calendar.js +541 -0
  116. package/dist/ok-carousel.js +352 -0
  117. package/dist/ok-chart.js +325 -0
  118. package/dist/ok-chat.js +320 -0
  119. package/dist/ok-coachmark.js +500 -0
  120. package/dist/ok-code.js +190 -0
  121. package/dist/ok-color-picker.js +569 -0
  122. package/dist/ok-combo.js +294 -0
  123. package/dist/ok-command-palette.js +448 -0
  124. package/dist/ok-contact-form.js +288 -0
  125. package/dist/ok-cropper.js +404 -0
  126. package/dist/ok-cta-band.js +134 -0
  127. package/dist/ok-currency.js +172 -0
  128. package/dist/ok-data-table.js +1281 -0
  129. package/dist/ok-date-picker.js +736 -0
  130. package/dist/ok-detail-list.js +156 -0
  131. package/dist/ok-diff.js +200 -0
  132. package/dist/ok-donut.js +280 -0
  133. package/dist/ok-drawer.js +357 -0
  134. package/dist/ok-dropzone.js +376 -0
  135. package/dist/ok-empty-state.js +104 -0
  136. package/dist/ok-error-page.js +547 -0
  137. package/dist/ok-event-card.js +384 -0
  138. package/dist/ok-feature-card.js +152 -0
  139. package/dist/ok-file-item.js +259 -0
  140. package/dist/ok-file-manager.js +1116 -0
  141. package/dist/ok-footer.js +67 -0
  142. package/dist/ok-funnel.js +181 -0
  143. package/dist/ok-gallery.js +293 -0
  144. package/dist/ok-gauge.js +385 -0
  145. package/dist/ok-heatmap.js +268 -0
  146. package/dist/ok-hero.js +43 -0
  147. package/dist/ok-hover-card.js +480 -0
  148. package/dist/ok-icon-tile.js +123 -0
  149. package/dist/ok-image.js +471 -0
  150. package/dist/ok-inline-feedback.js +221 -0
  151. package/dist/ok-invoice.js +229 -0
  152. package/dist/ok-json-viewer.js +330 -0
  153. package/dist/ok-kanban.js +427 -0
  154. package/dist/ok-kbd.js +159 -0
  155. package/dist/ok-keyboard.js +402 -0
  156. package/dist/ok-kpi.js +147 -0
  157. package/dist/ok-language-select.js +188 -0
  158. package/dist/ok-lightbox.js +490 -0
  159. package/dist/ok-logo-cloud.js +92 -0
  160. package/dist/ok-loyalty-card.js +353 -0
  161. package/dist/ok-mail.js +562 -0
  162. package/dist/ok-menu.js +529 -0
  163. package/dist/ok-menubar.js +628 -0
  164. package/dist/ok-navbar.js +306 -0
  165. package/dist/ok-notification-center.js +545 -0
  166. package/dist/ok-org-chart.js +619 -0
  167. package/dist/ok-otp.js +199 -0
  168. package/dist/ok-page-header.js +202 -0
  169. package/dist/ok-pagination.js +366 -0
  170. package/dist/ok-pdf.js +160 -0
  171. package/dist/ok-phone.js +225 -0
  172. package/dist/ok-pinpad.js +171 -0
  173. package/dist/ok-pricing-card.js +184 -0
  174. package/dist/ok-product-card.js +178 -0
  175. package/dist/ok-qr.js +652 -0
  176. package/dist/ok-qty-stepper.js +212 -0
  177. package/dist/ok-range-dual.js +280 -0
  178. package/dist/ok-rating.js +199 -0
  179. package/dist/ok-receipt.js +183 -0
  180. package/dist/ok-reveal.js +94 -0
  181. package/dist/ok-rich-text.js +538 -0
  182. package/dist/ok-scheduler.js +518 -0
  183. package/dist/ok-select-card.js +231 -0
  184. package/dist/ok-signature.js +267 -0
  185. package/dist/ok-skeleton.js +345 -0
  186. package/dist/ok-sparkline.js +150 -0
  187. package/dist/ok-split-button.js +251 -0
  188. package/dist/ok-splitter.js +289 -0
  189. package/dist/ok-stat.js +77 -0
  190. package/dist/ok-status-dot.js +163 -0
  191. package/dist/ok-status-pill.js +123 -0
  192. package/dist/ok-stepper.js +299 -0
  193. package/dist/ok-store.js +83 -0
  194. package/dist/ok-tag-input.js +358 -0
  195. package/dist/ok-testimonial.js +136 -0
  196. package/dist/ok-time-picker.js +472 -0
  197. package/dist/ok-timeline.js +251 -0
  198. package/dist/ok-tree.js +266 -0
  199. package/dist/ok-video.js +362 -0
  200. package/dist/ok-widget-board.js +265 -0
  201. package/dist/ok-wizard.js +153 -0
  202. package/dist/outfitkit.js +96 -0
  203. package/dist/shared/anchor.js +14 -0
  204. package/dist/store/controller.d.ts +17 -0
  205. package/dist/store/idb.d.ts +16 -0
  206. package/dist/store/store.d.ts +39 -0
  207. package/dist/store-controller.js +31 -0
  208. package/dist/store.js +182 -0
  209. package/dist/theme.example.css +70 -0
  210. package/package.json +147 -0
@@ -0,0 +1,352 @@
1
+ import { LitElement, css, html } from "lit";
2
+ import { property, state, query } from "lit/decorators.js";
3
+ import { define } from "./define.js";
4
+ var __defProp = Object.defineProperty;
5
+ var __decorateClass = (decorators, target, key, kind) => {
6
+ var result = void 0;
7
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
8
+ if (decorator = decorators[i])
9
+ result = decorator(target, key, result) || result;
10
+ if (result) __defProp(target, key, result);
11
+ return result;
12
+ };
13
+ const DEFAULT_LABELS = {
14
+ previous: "Previous",
15
+ next: "Next",
16
+ goToSlide: "Go to slide {n}"
17
+ };
18
+ class OkCarousel extends LitElement {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.slides = [];
22
+ this.index = 0;
23
+ this.autoplay = 0;
24
+ this.loop = false;
25
+ this.labels = {};
26
+ this.slottedCount = 0;
27
+ this.dragStartX = 0;
28
+ this.dragging = false;
29
+ this.dragDelta = 0;
30
+ }
31
+ static {
32
+ this.styles = css`
33
+ :host {
34
+ /* Vars overridable (estilo Ionic), default = cadena --ok-* → --ion-* → hex */
35
+ --bg: var(--ok-surface, var(--ion-background-color, #ffffff));
36
+ --color: var(--ok-text, var(--ion-text-color, #1c1b17));
37
+ --primary-color: var(--ok-primary, var(--ion-color-primary, #3880ff));
38
+ --dot-color: var(--ok-border, rgba(var(--ion-text-color-rgb, 28, 27, 23), 0.25));
39
+ --dot-active: var(--ok-primary, var(--ion-color-primary, #3880ff));
40
+ --arrow-bg: var(--ok-surface, var(--ion-background-color, #ffffff));
41
+ --shadow: var(--ok-shadow, 0 2px 10px rgba(0, 0, 0, 0.15));
42
+ --border-radius: var(--ok-radius, 12px);
43
+ --height: var(--ok-carousel-height, 260px);
44
+ --font: var(--ok-font, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);
45
+
46
+ /* Ocupa el ancho del contenedor y es responsive. */
47
+ display: block;
48
+ width: 100%;
49
+ color: var(--color);
50
+ font-family: var(--font);
51
+ }
52
+ /* Ventana del carrusel: recorta los slides; el track se desplaza dentro. */
53
+ .viewport {
54
+ position: relative;
55
+ width: 100%;
56
+ height: var(--height);
57
+ overflow: hidden;
58
+ border-radius: var(--border-radius);
59
+ background: var(--bg);
60
+ touch-action: pan-y;
61
+ }
62
+ /* Pista horizontal con todos los slides en fila; se mueve con translateX. */
63
+ .track {
64
+ display: flex;
65
+ height: 100%;
66
+ width: 100%;
67
+ transition: transform 0.35s ease;
68
+ will-change: transform;
69
+ }
70
+ /* Mientras se arrastra con el dedo, sin transición (sigue al puntero). */
71
+ .track.dragging {
72
+ transition: none;
73
+ }
74
+ .slide {
75
+ flex: 0 0 100%;
76
+ width: 100%;
77
+ height: 100%;
78
+ box-sizing: border-box;
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ overflow: hidden;
83
+ }
84
+ /* Cuando los slides vienen de .slides (HTML/string). */
85
+ .slide.from-prop {
86
+ padding: 1rem;
87
+ text-align: center;
88
+ }
89
+ .slide ::slotted(*) {
90
+ width: 100%;
91
+ height: 100%;
92
+ }
93
+ /* Flechas de navegación, superpuestas a izquierda/derecha y centradas verticalmente. */
94
+ .arrow {
95
+ position: absolute;
96
+ top: 50%;
97
+ transform: translateY(-50%);
98
+ z-index: 2;
99
+ --background: var(--arrow-bg);
100
+ --color: var(--color);
101
+ --border-radius: 50%;
102
+ --box-shadow: var(--shadow);
103
+ --padding-start: 0;
104
+ --padding-end: 0;
105
+ margin: 0;
106
+ width: 40px;
107
+ height: 40px;
108
+ }
109
+ .arrow.prev {
110
+ left: 8px;
111
+ }
112
+ .arrow.next {
113
+ right: 8px;
114
+ }
115
+ .arrow[disabled] {
116
+ opacity: 0.35;
117
+ }
118
+ /* Tira de puntos indicadores bajo la ventana. */
119
+ .dots {
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ gap: 0.5rem;
124
+ margin-top: 0.6rem;
125
+ }
126
+ .dot {
127
+ width: 9px;
128
+ height: 9px;
129
+ padding: 0;
130
+ border: 0;
131
+ border-radius: 50%;
132
+ background: var(--dot-color);
133
+ cursor: pointer;
134
+ transition: background-color var(--ok-transition, 150ms ease), color var(--ok-transition, 150ms ease),
135
+ border-color var(--ok-transition, 150ms ease), box-shadow var(--ok-transition, 150ms ease),
136
+ transform 120ms ease;
137
+ }
138
+ .dot.active {
139
+ background: var(--dot-active);
140
+ transform: scale(1.25);
141
+ }
142
+ @media (hover: hover) {
143
+ .dot:not(.active):hover {
144
+ background: var(--dot-active);
145
+ transform: scale(1.15);
146
+ }
147
+ }
148
+ .dot:active {
149
+ transform: scale(var(--ok-press-scale, 0.97));
150
+ }
151
+ @media (prefers-reduced-motion: reduce) {
152
+ .dot:hover,
153
+ .dot:active {
154
+ transform: none;
155
+ }
156
+ }
157
+ /* En móvil, oculta las flechas y deja navegar por swipe + puntos. */
158
+ @media (max-width: 480px) {
159
+ .arrow {
160
+ width: 34px;
161
+ height: 34px;
162
+ }
163
+ }
164
+ `;
165
+ }
166
+ get t() {
167
+ return { ...DEFAULT_LABELS, ...this.labels };
168
+ }
169
+ disconnectedCallback() {
170
+ super.disconnectedCallback();
171
+ this.stopAutoplay();
172
+ }
173
+ updated(changed) {
174
+ if (changed.has("autoplay") || changed.has("slides")) {
175
+ this.restartAutoplay();
176
+ }
177
+ }
178
+ // Total de slides según la fuente activa (datos > slot).
179
+ get count() {
180
+ return this.slides.length > 0 ? this.slides.length : this.slottedCount;
181
+ }
182
+ // Lee cuántos slides hay en el slot por defecto (un hijo = un slide).
183
+ onSlotChange(e) {
184
+ const slot = e.target;
185
+ this.slottedCount = slot.assignedElements().length;
186
+ }
187
+ // Mueve el carrusel a un índice concreto (respeta loop) y emite `ok-change`.
188
+ goTo(i, emit = true) {
189
+ const n = this.count;
190
+ if (n === 0) return;
191
+ let next = i;
192
+ if (next < 0) next = this.loop ? n - 1 : 0;
193
+ if (next > n - 1) next = this.loop ? 0 : n - 1;
194
+ if (next === this.index) return;
195
+ this.index = next;
196
+ if (emit) {
197
+ this.dispatchEvent(
198
+ new CustomEvent("ok-change", {
199
+ detail: { index: this.index },
200
+ bubbles: true,
201
+ composed: true
202
+ })
203
+ );
204
+ }
205
+ }
206
+ next() {
207
+ this.goTo(this.index + 1);
208
+ this.restartAutoplay();
209
+ }
210
+ prev() {
211
+ this.goTo(this.index - 1);
212
+ this.restartAutoplay();
213
+ }
214
+ // ---- Autoplay -----------------------------------------------------------
215
+ restartAutoplay() {
216
+ this.stopAutoplay();
217
+ if (this.autoplay > 0 && this.count > 1) {
218
+ this.autoplayTimer = setInterval(() => {
219
+ if (!this.loop && this.index >= this.count - 1) {
220
+ this.goTo(0);
221
+ } else {
222
+ this.goTo(this.index + 1);
223
+ }
224
+ }, this.autoplay);
225
+ }
226
+ }
227
+ stopAutoplay() {
228
+ if (this.autoplayTimer) {
229
+ clearInterval(this.autoplayTimer);
230
+ this.autoplayTimer = void 0;
231
+ }
232
+ }
233
+ // ---- Swipe táctil (pointer events) --------------------------------------
234
+ onPointerDown(e) {
235
+ if (this.count <= 1) return;
236
+ this.dragging = true;
237
+ this.dragStartX = e.clientX;
238
+ this.dragDelta = 0;
239
+ this.stopAutoplay();
240
+ e.currentTarget.setPointerCapture?.(e.pointerId);
241
+ }
242
+ onPointerMove(e) {
243
+ if (!this.dragging) return;
244
+ this.dragDelta = e.clientX - this.dragStartX;
245
+ if (this.trackEl) {
246
+ const base = -this.index * 100;
247
+ const pct = this.dragDelta / (this.offsetWidth || 1) * 100;
248
+ this.trackEl.style.transform = `translateX(${base + pct}%)`;
249
+ }
250
+ }
251
+ onPointerUp() {
252
+ if (!this.dragging) return;
253
+ this.dragging = false;
254
+ const threshold = (this.offsetWidth || 1) * 0.18;
255
+ if (this.dragDelta <= -threshold) this.goTo(this.index + 1);
256
+ else if (this.dragDelta >= threshold) this.goTo(this.index - 1);
257
+ if (this.trackEl) this.trackEl.style.transform = "";
258
+ this.dragDelta = 0;
259
+ this.restartAutoplay();
260
+ }
261
+ render() {
262
+ const n = this.count;
263
+ const fromProp = this.slides.length > 0;
264
+ const atStart = this.index <= 0;
265
+ const atEnd = this.index >= n - 1;
266
+ return html`
267
+ <div class="viewport">
268
+ <ion-button
269
+ class="arrow prev"
270
+ fill="clear"
271
+ aria-label=${this.t.previous}
272
+ ?disabled=${n <= 1 || !this.loop && atStart}
273
+ @click=${() => this.prev()}
274
+ >
275
+ <ion-icon slot="icon-only" name="chevron-back-outline"></ion-icon>
276
+ </ion-button>
277
+
278
+ <div
279
+ class=${`track ${this.dragging ? "dragging" : ""}`.trim()}
280
+ style=${`transform: translateX(-${this.index * 100}%)`}
281
+ @pointerdown=${this.onPointerDown}
282
+ @pointermove=${this.onPointerMove}
283
+ @pointerup=${this.onPointerUp}
284
+ @pointercancel=${this.onPointerUp}
285
+ @pointerleave=${this.onPointerUp}
286
+ >
287
+ ${fromProp ? this.slides.map(
288
+ (s) => html`<div class="slide from-prop">${this.unsafeSlide(s)}</div>`
289
+ ) : html`<div class="slide">
290
+ <slot @slotchange=${this.onSlotChange}></slot>
291
+ </div>`}
292
+ </div>
293
+
294
+ <ion-button
295
+ class="arrow next"
296
+ fill="clear"
297
+ aria-label=${this.t.next}
298
+ ?disabled=${n <= 1 || !this.loop && atEnd}
299
+ @click=${() => this.next()}
300
+ >
301
+ <ion-icon slot="icon-only" name="chevron-forward-outline"></ion-icon>
302
+ </ion-button>
303
+ </div>
304
+
305
+ ${n > 1 ? html`<div class="dots" role="tablist">
306
+ ${Array.from({ length: n }).map(
307
+ (_, i) => html`<button
308
+ type="button"
309
+ class=${`dot ${i === this.index ? "active" : ""}`.trim()}
310
+ role="tab"
311
+ aria-selected=${i === this.index ? "true" : "false"}
312
+ aria-label=${this.t.goToSlide.replace("{n}", String(i + 1))}
313
+ @click=${() => {
314
+ this.goTo(i);
315
+ this.restartAutoplay();
316
+ }}
317
+ ></button>`
318
+ )}
319
+ </div>` : ""}
320
+ `;
321
+ }
322
+ // Renderiza un slide aportado por `.slides`. Por seguridad CSP/XSS, NO inyectamos HTML crudo;
323
+ // se muestra como texto. (El consumidor que necesite HTML rico debe usar el `<slot>`.)
324
+ unsafeSlide(s) {
325
+ return html`${s}`;
326
+ }
327
+ }
328
+ __decorateClass([
329
+ property({ attribute: false })
330
+ ], OkCarousel.prototype, "slides");
331
+ __decorateClass([
332
+ property({ type: Number })
333
+ ], OkCarousel.prototype, "index");
334
+ __decorateClass([
335
+ property({ type: Number })
336
+ ], OkCarousel.prototype, "autoplay");
337
+ __decorateClass([
338
+ property({ type: Boolean })
339
+ ], OkCarousel.prototype, "loop");
340
+ __decorateClass([
341
+ property({ attribute: false })
342
+ ], OkCarousel.prototype, "labels");
343
+ __decorateClass([
344
+ state()
345
+ ], OkCarousel.prototype, "slottedCount");
346
+ __decorateClass([
347
+ query(".track")
348
+ ], OkCarousel.prototype, "trackEl");
349
+ define("ok-carousel", OkCarousel);
350
+ export {
351
+ OkCarousel
352
+ };
@@ -0,0 +1,325 @@
1
+ import { LitElement, css, svg, html } from "lit";
2
+ import { property } from "lit/decorators.js";
3
+ import { define } from "./define.js";
4
+ var __defProp = Object.defineProperty;
5
+ var __decorateClass = (decorators, target, key, kind) => {
6
+ var result = void 0;
7
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
8
+ if (decorator = decorators[i])
9
+ result = decorator(target, key, result) || result;
10
+ if (result) __defProp(target, key, result);
11
+ return result;
12
+ };
13
+ class OkChart extends LitElement {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.type = "line";
17
+ this.series = [];
18
+ this.labels = [];
19
+ this.axis = [];
20
+ this.gridlines = true;
21
+ this.height = 200;
22
+ this.endpoint = false;
23
+ this.endpointLabel = "";
24
+ this.vbWidth = 600;
25
+ }
26
+ static {
27
+ this.styles = css`
28
+ :host {
29
+ display: block;
30
+ width: 100%;
31
+ /* Tokens propios estilo Ionic (overridables): --ok-* → --ion-* → hex. */
32
+ --primary: var(--ok-primary, var(--ion-color-primary, #3880ff));
33
+ --grid: var(--ok-border-color, var(--ion-border-color, #e0e0e0));
34
+ --axis-color: var(--ok-color-medium, var(--ion-color-medium, #92949c));
35
+ --value-color: var(--ok-text-color, var(--ion-text-color, #1f2933));
36
+ --mute: var(--ok-color-step-200, var(--ion-color-step-200, #cccccc));
37
+ --surface: var(--ok-surface, var(--ion-background-color, #ffffff));
38
+ --legend-color: var(--ok-color-medium, var(--ion-color-medium, #92949c));
39
+ }
40
+
41
+ .chart {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: 0.75rem;
45
+ width: 100%;
46
+ box-sizing: border-box;
47
+ }
48
+
49
+ svg {
50
+ display: block;
51
+ width: 100%;
52
+ overflow: visible;
53
+ font-family: ui-monospace, 'SF Mono', 'Roboto Mono', Menlo, Consolas, monospace;
54
+ }
55
+
56
+ .grid line {
57
+ stroke: var(--grid);
58
+ stroke-width: 1;
59
+ shape-rendering: crispEdges;
60
+ }
61
+
62
+ .axis text {
63
+ fill: var(--axis-color);
64
+ font-size: 10px;
65
+ font-variant-numeric: tabular-nums;
66
+ }
67
+
68
+ .value-label {
69
+ fill: var(--value-color);
70
+ font-weight: 600;
71
+ font-size: 11px;
72
+ font-variant-numeric: tabular-nums;
73
+ }
74
+
75
+ .legend {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ gap: 0.75rem;
79
+ font-size: 0.72rem;
80
+ color: var(--legend-color);
81
+ }
82
+ .legend-item {
83
+ display: inline-flex;
84
+ align-items: center;
85
+ gap: 0.375rem;
86
+ }
87
+ .legend-dot {
88
+ width: 8px;
89
+ height: 8px;
90
+ border-radius: 2px;
91
+ flex-shrink: 0;
92
+ }
93
+ .legend-dot.dashed {
94
+ height: 2px;
95
+ border-radius: 1px;
96
+ }
97
+ `;
98
+ }
99
+ get vbHeight() {
100
+ return this.height;
101
+ }
102
+ // Margen para dejar sitio al eje de valor (izq) y a las etiquetas X (abajo).
103
+ get pad() {
104
+ return {
105
+ left: this.axis.length ? 44 : 12,
106
+ right: this.endpoint ? 56 : 12,
107
+ top: 12,
108
+ bottom: this.labels.length ? 22 : 12
109
+ };
110
+ }
111
+ get plotW() {
112
+ const p = this.pad;
113
+ return this.vbWidth - p.left - p.right;
114
+ }
115
+ get plotH() {
116
+ const p = this.pad;
117
+ return this.vbHeight - p.top - p.bottom;
118
+ }
119
+ // Mínimo/máximo global de todas las series (las barras crecen desde 0).
120
+ get bounds() {
121
+ const all = [];
122
+ for (const s of this.series ?? []) for (const v of s.data ?? []) all.push(v);
123
+ if (!all.length) return { min: 0, max: 1 };
124
+ let min = Math.min(...all);
125
+ let max = Math.max(...all);
126
+ if (this.type !== "line") min = Math.min(min, 0);
127
+ if (min === max) max = min + 1;
128
+ return { min, max };
129
+ }
130
+ // Color efectivo de una serie (prop o el token primario del componente).
131
+ seriesColor(s, muted = false) {
132
+ if (s.mute || muted) return s.color ?? "var(--mute)";
133
+ return s.color || "var(--primary)";
134
+ }
135
+ // Mapea (índice, valor) → coordenadas {x, y} del área de dibujo.
136
+ xAt(i, n) {
137
+ const p = this.pad;
138
+ if (n <= 1) return p.left + this.plotW / 2;
139
+ return p.left + i / (n - 1) * this.plotW;
140
+ }
141
+ yAt(value) {
142
+ const { min, max } = this.bounds;
143
+ const p = this.pad;
144
+ return p.top + (1 - (value - min) / (max - min)) * this.plotH;
145
+ }
146
+ // ---- Rejilla horizontal ----
147
+ renderGrid() {
148
+ if (!this.gridlines) return svg``;
149
+ const p = this.pad;
150
+ const rows = Math.max(this.axis.length || 4, 2);
151
+ const lines = [];
152
+ for (let i = 0; i < rows; i++) {
153
+ const y = p.top + i / (rows - 1) * this.plotH;
154
+ lines.push(svg`<line x1=${p.left} x2=${this.vbWidth - p.right} y1=${y} y2=${y} />`);
155
+ }
156
+ return svg`<g class="grid">${lines}</g>`;
157
+ }
158
+ // ---- Eje de valor (izquierda) ----
159
+ renderValueAxis() {
160
+ if (!this.axis.length) return svg``;
161
+ const p = this.pad;
162
+ const n = this.axis.length;
163
+ const ticks = this.axis.map((t, i) => {
164
+ const y = n > 1 ? p.top + i / (n - 1) * this.plotH : p.top + this.plotH / 2;
165
+ return svg`<text x=${p.left - 8} y=${y + 3} text-anchor="end">${t}</text>`;
166
+ });
167
+ return svg`<g class="axis">${ticks}</g>`;
168
+ }
169
+ // ---- Etiquetas del eje X (abajo) ----
170
+ renderXLabels() {
171
+ if (!this.labels.length) return svg``;
172
+ const n = this.labels.length;
173
+ const y = this.vbHeight - this.pad.bottom + 14;
174
+ const ticks = this.labels.map((t, i) => {
175
+ const x = this.xAt(i, n);
176
+ const anchor = i === 0 ? "start" : i === n - 1 ? "end" : "middle";
177
+ return svg`<text x=${x} y=${y} text-anchor=${anchor}>${t}</text>`;
178
+ });
179
+ return svg`<g class="axis">${ticks}</g>`;
180
+ }
181
+ // ---- Líneas / áreas ----
182
+ renderLines() {
183
+ const fillArea = this.type === "area";
184
+ const parts = [];
185
+ (this.series ?? []).forEach((s, si) => {
186
+ const data = s.data ?? [];
187
+ const n = data.length;
188
+ if (!n) return;
189
+ const color = this.seriesColor(s);
190
+ const pts = data.map((v, i) => `${this.xAt(i, n)},${this.yAt(v)}`);
191
+ const linePath = `M${pts.join(" L")}`;
192
+ if (fillArea && !s.dashed) {
193
+ const baseY = this.pad.top + this.plotH;
194
+ const x0 = this.xAt(0, n);
195
+ const xEnd = this.xAt(n - 1, n);
196
+ const areaPath = `${linePath} L${xEnd},${baseY} L${x0},${baseY} Z`;
197
+ const gid = `ok-chart-grad-${si}`;
198
+ parts.push(svg`
199
+ <defs>
200
+ <linearGradient id=${gid} x1="0" x2="0" y1="0" y2="1">
201
+ <stop offset="0%" stop-color=${color} stop-opacity="0.5" />
202
+ <stop offset="100%" stop-color=${color} stop-opacity="0" />
203
+ </linearGradient>
204
+ </defs>
205
+ <path d=${areaPath} fill=${`url(#${gid})`} stroke="none" />
206
+ `);
207
+ }
208
+ parts.push(svg`<path
209
+ d=${linePath}
210
+ fill="none"
211
+ stroke=${color}
212
+ stroke-width=${s.dashed ? 1.5 : 2}
213
+ stroke-linecap="round"
214
+ stroke-linejoin="round"
215
+ stroke-dasharray=${s.dashed ? "4 4" : ""}
216
+ />`);
217
+ if (this.endpoint && si === 0 && n) {
218
+ const lastX = this.xAt(n - 1, n);
219
+ const lastY = this.yAt(data[n - 1]);
220
+ const label = this.endpointLabel || String(data[n - 1]);
221
+ parts.push(svg`
222
+ <circle cx=${lastX} cy=${lastY} r="4" fill=${color}
223
+ stroke="var(--surface)" stroke-width="2" />
224
+ <text class="value-label" x=${lastX + 10} y=${lastY + 3}>${label}</text>
225
+ `);
226
+ }
227
+ });
228
+ return svg`${parts}`;
229
+ }
230
+ // ---- Barras agrupadas (rounded rx=2, soporte mute por serie) ----
231
+ renderBars() {
232
+ const series = this.series ?? [];
233
+ const groups = Math.max(...series.map((s) => s.data?.length ?? 0), 0);
234
+ if (!groups) return svg``;
235
+ const p = this.pad;
236
+ const baseY = this.yAt(this.bounds.min < 0 ? 0 : this.bounds.min);
237
+ const groupW = this.plotW / groups;
238
+ const innerGap = 0.28;
239
+ const usable = groupW * (1 - innerGap);
240
+ const nSeries = series.length || 1;
241
+ const barW = Math.max(usable / nSeries, 1);
242
+ const rects = [];
243
+ for (let g = 0; g < groups; g++) {
244
+ series.forEach((s, si) => {
245
+ const v = s.data?.[g];
246
+ if (v == null) return;
247
+ const x = p.left + g * groupW + (groupW - usable) / 2 + si * barW;
248
+ const y = this.yAt(v);
249
+ const top = Math.min(y, baseY);
250
+ const h = Math.max(Math.abs(baseY - y), 0.5);
251
+ const color = this.seriesColor(s);
252
+ rects.push(svg`<rect
253
+ x=${x + 0.5}
254
+ y=${top}
255
+ width=${Math.max(barW - 1, 1)}
256
+ height=${h}
257
+ rx="2"
258
+ fill=${color}
259
+ />`);
260
+ });
261
+ }
262
+ return svg`<g>${rects}</g>`;
263
+ }
264
+ // ---- Leyenda (si alguna serie tiene nombre) ----
265
+ renderLegend() {
266
+ const items = (this.series ?? []).filter((s) => s.name);
267
+ if (!items.length) return null;
268
+ return html`<div class="legend">
269
+ ${items.map(
270
+ (s) => html`<span class="legend-item">
271
+ <span
272
+ class=${s.dashed ? "legend-dot dashed" : "legend-dot"}
273
+ style=${`background:${this.seriesColor(s)}`}
274
+ ></span>
275
+ ${s.name}
276
+ </span>`
277
+ )}
278
+ </div>`;
279
+ }
280
+ render() {
281
+ const body = this.type === "bar" ? this.renderBars() : this.renderLines();
282
+ return html`
283
+ <div class="chart">
284
+ <svg
285
+ viewBox=${`0 0 ${this.vbWidth} ${this.vbHeight}`}
286
+ style=${`height:${this.height}px`}
287
+ preserveAspectRatio="none"
288
+ role="img"
289
+ aria-label=${(this.series ?? []).map((s) => s.name).filter(Boolean).join(", ") || "chart"}
290
+ >
291
+ ${this.renderGrid()} ${this.renderValueAxis()} ${this.renderXLabels()} ${body}
292
+ </svg>
293
+ ${this.renderLegend()}
294
+ </div>
295
+ `;
296
+ }
297
+ }
298
+ __decorateClass([
299
+ property()
300
+ ], OkChart.prototype, "type");
301
+ __decorateClass([
302
+ property({ attribute: false })
303
+ ], OkChart.prototype, "series");
304
+ __decorateClass([
305
+ property({ attribute: false })
306
+ ], OkChart.prototype, "labels");
307
+ __decorateClass([
308
+ property({ attribute: false })
309
+ ], OkChart.prototype, "axis");
310
+ __decorateClass([
311
+ property({ type: Boolean })
312
+ ], OkChart.prototype, "gridlines");
313
+ __decorateClass([
314
+ property({ type: Number })
315
+ ], OkChart.prototype, "height");
316
+ __decorateClass([
317
+ property({ type: Boolean })
318
+ ], OkChart.prototype, "endpoint");
319
+ __decorateClass([
320
+ property()
321
+ ], OkChart.prototype, "endpointLabel");
322
+ define("ok-chart", OkChart);
323
+ export {
324
+ OkChart
325
+ };