@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,569 @@
1
+ import { LitElement, css, html } from "lit";
2
+ import { property, state } 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_PRESETS = [
14
+ "#3880ff",
15
+ // primary
16
+ "#3dc2ff",
17
+ // secondary
18
+ "#5260ff",
19
+ // tertiary
20
+ "#2dd36f",
21
+ // success
22
+ "#ffc409",
23
+ // warning
24
+ "#eb445a",
25
+ // danger
26
+ "#92949c",
27
+ // medium
28
+ "#222428",
29
+ // dark
30
+ "#ffffff",
31
+ // white
32
+ "#000000"
33
+ // black
34
+ ];
35
+ function clamp(n, min, max) {
36
+ return Math.min(max, Math.max(min, n));
37
+ }
38
+ function hsvToRgb(h, s, v) {
39
+ const c = v * s;
40
+ const hh = (h % 360 + 360) % 360 / 60;
41
+ const x = c * (1 - Math.abs(hh % 2 - 1));
42
+ let r1 = 0;
43
+ let g1 = 0;
44
+ let b1 = 0;
45
+ if (hh >= 0 && hh < 1) [r1, g1, b1] = [c, x, 0];
46
+ else if (hh < 2) [r1, g1, b1] = [x, c, 0];
47
+ else if (hh < 3) [r1, g1, b1] = [0, c, x];
48
+ else if (hh < 4) [r1, g1, b1] = [0, x, c];
49
+ else if (hh < 5) [r1, g1, b1] = [x, 0, c];
50
+ else [r1, g1, b1] = [c, 0, x];
51
+ const m = v - c;
52
+ return {
53
+ r: Math.round((r1 + m) * 255),
54
+ g: Math.round((g1 + m) * 255),
55
+ b: Math.round((b1 + m) * 255)
56
+ };
57
+ }
58
+ function rgbToHsv(r, g, b) {
59
+ const rn = r / 255;
60
+ const gn = g / 255;
61
+ const bn = b / 255;
62
+ const max = Math.max(rn, gn, bn);
63
+ const min = Math.min(rn, gn, bn);
64
+ const delta = max - min;
65
+ let h = 0;
66
+ if (delta !== 0) {
67
+ if (max === rn) h = (gn - bn) / delta % 6;
68
+ else if (max === gn) h = (bn - rn) / delta + 2;
69
+ else h = (rn - gn) / delta + 4;
70
+ h *= 60;
71
+ if (h < 0) h += 360;
72
+ }
73
+ const s = max === 0 ? 0 : delta / max;
74
+ return { h, s, v: max };
75
+ }
76
+ function toHex2(n) {
77
+ return clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0");
78
+ }
79
+ function rgbToHex({ r, g, b }) {
80
+ return `#${toHex2(r)}${toHex2(g)}${toHex2(b)}`;
81
+ }
82
+ function hexToRgb(hex) {
83
+ let h = hex.trim().replace(/^#/, "");
84
+ if (/^[0-9a-fA-F]{3}$/.test(h)) {
85
+ h = h.split("").map((c) => c + c).join("");
86
+ }
87
+ if (!/^[0-9a-fA-F]{6}$/.test(h)) return null;
88
+ return {
89
+ r: parseInt(h.slice(0, 2), 16),
90
+ g: parseInt(h.slice(2, 4), 16),
91
+ b: parseInt(h.slice(4, 6), 16)
92
+ };
93
+ }
94
+ function normalizeHex(hex) {
95
+ const rgb = hexToRgb(hex);
96
+ return rgb ? rgbToHex(rgb) : null;
97
+ }
98
+ const DEFAULT_LABELS = {
99
+ triggerLabel: "Select color",
100
+ panelLabel: "Color picker",
101
+ hexLabel: "Hex value"
102
+ };
103
+ class OkColorPicker extends LitElement {
104
+ constructor() {
105
+ super(...arguments);
106
+ this.value = "#3880ff";
107
+ this.presets = DEFAULT_PRESETS;
108
+ this.labels = {};
109
+ this.open = false;
110
+ this.h = 0;
111
+ this.s = 0;
112
+ this.v = 0;
113
+ this.hexInput = "#3880ff";
114
+ this.hexInvalid = false;
115
+ this.dragging = null;
116
+ this.onDocClick = (e) => {
117
+ if (!e.composedPath().includes(this)) this.close();
118
+ };
119
+ this.onKeydown = (e) => {
120
+ if (e.key === "Escape") this.close();
121
+ };
122
+ this.onPointerMove = (e) => {
123
+ if (this.dragging === "sv") this.updateSvFromPointer(e.clientX, e.clientY);
124
+ else if (this.dragging === "hue") this.updateHueFromPointer(e.clientX);
125
+ };
126
+ this.onPointerUp = () => {
127
+ this.unbindDrag();
128
+ };
129
+ }
130
+ static {
131
+ this.styles = css`
132
+ :host {
133
+ /* Vars overridable (estilo Ionic), default = cadena --ok-* → --ion-* → hex */
134
+ --color: var(--ok-text, var(--ion-text-color, #1c1b17));
135
+ --color-muted: var(--ok-text-muted, rgba(var(--ion-text-color-rgb, 28, 27, 23), 0.6));
136
+ --border-color: var(--ok-border, rgba(var(--ion-text-color-rgb, 28, 27, 23), 0.18));
137
+ --panel-bg: var(--ok-surface, var(--ion-card-background, var(--ion-background-color, #ffffff)));
138
+ --border-radius: var(--ok-radius, 10px);
139
+ --shadow: var(--ok-shadow, 0 8px 28px rgba(0, 0, 0, 0.18));
140
+ --font: var(--ok-font, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);
141
+ --checker: var(
142
+ --ok-checker,
143
+ linear-gradient(45deg, #ccc 25%, transparent 25%),
144
+ linear-gradient(-45deg, #ccc 25%, transparent 25%),
145
+ linear-gradient(45deg, transparent 75%, #ccc 75%),
146
+ linear-gradient(-45deg, transparent 75%, #ccc 75%)
147
+ );
148
+
149
+ /* INLINE: solo lo que mide el swatch disparador. */
150
+ display: inline-block;
151
+ position: relative;
152
+ color: var(--color);
153
+ font-family: var(--font);
154
+ }
155
+ /* Disparador: muestra cuadrada con el color actual (sobre damero para alfa visual). */
156
+ .swatch {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ justify-content: center;
160
+ width: 36px;
161
+ height: 36px;
162
+ padding: 0;
163
+ border: 1px solid var(--border-color);
164
+ border-radius: 8px;
165
+ cursor: pointer;
166
+ overflow: hidden;
167
+ background-color: #fff;
168
+ background-image: var(--checker);
169
+ background-size: 12px 12px;
170
+ background-position: 0 0, 0 6px, 6px -6px, -6px 0;
171
+ transition: background-color var(--ok-transition, 150ms ease),
172
+ color var(--ok-transition, 150ms ease),
173
+ border-color var(--ok-transition, 150ms ease),
174
+ box-shadow var(--ok-transition, 150ms ease), transform 120ms ease;
175
+ }
176
+ @media (hover: hover) {
177
+ .swatch:hover {
178
+ border-color: var(--color-muted);
179
+ }
180
+ }
181
+ .swatch:active {
182
+ transform: scale(var(--ok-press-scale, 0.97));
183
+ }
184
+ .swatch .fill {
185
+ width: 100%;
186
+ height: 100%;
187
+ }
188
+ /* Panel/popover propio bajo el swatch (ancho de menú web, no demasiado ancho). */
189
+ .panel {
190
+ position: absolute;
191
+ top: calc(100% + 8px);
192
+ left: 0;
193
+ z-index: 1000;
194
+ width: 240px;
195
+ max-width: 90vw;
196
+ padding: 0.75rem;
197
+ background: var(--panel-bg);
198
+ border: 1px solid var(--border-color);
199
+ border-radius: var(--border-radius);
200
+ box-shadow: var(--shadow);
201
+ box-sizing: border-box;
202
+ }
203
+ /* Área de Saturación (X: blanco→color) y Valor (Y: transparente→negro). */
204
+ .sv {
205
+ position: relative;
206
+ width: 100%;
207
+ height: 140px;
208
+ border-radius: 6px;
209
+ cursor: crosshair;
210
+ touch-action: none;
211
+ background-image: linear-gradient(to top, #000, transparent),
212
+ linear-gradient(to right, #fff, var(--hue-color, #f00));
213
+ overflow: hidden;
214
+ }
215
+ .sv .thumb {
216
+ position: absolute;
217
+ width: 14px;
218
+ height: 14px;
219
+ margin: -7px 0 0 -7px;
220
+ border-radius: 50%;
221
+ border: 2px solid #fff;
222
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
223
+ pointer-events: none;
224
+ }
225
+ /* Slider de Tono: barra arcoíris horizontal con thumb arrastrable. */
226
+ .hue {
227
+ position: relative;
228
+ width: 100%;
229
+ height: 14px;
230
+ margin-top: 0.7rem;
231
+ border-radius: 7px;
232
+ cursor: pointer;
233
+ touch-action: none;
234
+ background: linear-gradient(
235
+ to right,
236
+ #f00 0%,
237
+ #ff0 17%,
238
+ #0f0 33%,
239
+ #0ff 50%,
240
+ #00f 67%,
241
+ #f0f 83%,
242
+ #f00 100%
243
+ );
244
+ }
245
+ .hue .thumb {
246
+ position: absolute;
247
+ top: 50%;
248
+ width: 14px;
249
+ height: 14px;
250
+ margin: -7px 0 0 -7px;
251
+ border-radius: 50%;
252
+ border: 2px solid #fff;
253
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
254
+ background: var(--hue-color, #f00);
255
+ pointer-events: none;
256
+ }
257
+ /* Fila de hex (preview + input editable). */
258
+ .hexrow {
259
+ display: flex;
260
+ align-items: center;
261
+ gap: 0.5rem;
262
+ margin-top: 0.7rem;
263
+ }
264
+ .hexrow .preview {
265
+ flex: 0 0 auto;
266
+ width: 28px;
267
+ height: 28px;
268
+ border-radius: 6px;
269
+ border: 1px solid var(--border-color);
270
+ }
271
+ .hexrow input.hex {
272
+ flex: 1 1 auto;
273
+ min-width: 0;
274
+ box-sizing: border-box;
275
+ padding: 0.4rem 0.5rem;
276
+ font: inherit;
277
+ font-size: 0.85rem;
278
+ color: var(--color);
279
+ background: transparent;
280
+ border: 1px solid var(--border-color);
281
+ border-radius: 6px;
282
+ text-transform: lowercase;
283
+ }
284
+ .hexrow input.hex:focus {
285
+ outline: none;
286
+ border-color: var(--ok-primary, var(--ion-color-primary, #3880ff));
287
+ }
288
+ .hexrow input.hex.invalid {
289
+ border-color: var(--ok-danger, var(--ion-color-danger, #eb445a));
290
+ }
291
+ /* Fila de swatches preset. */
292
+ .presets {
293
+ display: flex;
294
+ flex-wrap: wrap;
295
+ gap: 0.3rem;
296
+ margin-top: 0.7rem;
297
+ }
298
+ .presets button {
299
+ width: 20px;
300
+ height: 20px;
301
+ padding: 0;
302
+ border: 1px solid var(--border-color);
303
+ border-radius: 5px;
304
+ cursor: pointer;
305
+ transition: background-color var(--ok-transition, 150ms ease),
306
+ color var(--ok-transition, 150ms ease),
307
+ border-color var(--ok-transition, 150ms ease),
308
+ box-shadow var(--ok-transition, 150ms ease), transform 120ms ease;
309
+ }
310
+ @media (hover: hover) {
311
+ .presets button:hover {
312
+ border-color: var(--color-muted);
313
+ }
314
+ }
315
+ .presets button:active {
316
+ transform: scale(var(--ok-press-scale, 0.97));
317
+ }
318
+ .presets button.active {
319
+ box-shadow: 0 0 0 2px var(--panel-bg), 0 0 0 4px var(--ok-primary, var(--ion-color-primary, #3880ff));
320
+ }
321
+ @media (prefers-reduced-motion: reduce) {
322
+ .swatch:active,
323
+ .presets button:active {
324
+ transform: none;
325
+ }
326
+ }
327
+ `;
328
+ }
329
+ // Textos efectivos: defaults inglés sobreescritos por los pasados desde fuera.
330
+ get t() {
331
+ return { ...DEFAULT_LABELS, ...this.labels };
332
+ }
333
+ // Sincroniza el estado HSV interno desde la prop `value` (al conectar y en cambios externos).
334
+ syncFromValue() {
335
+ const rgb = hexToRgb(this.value);
336
+ if (!rgb) return;
337
+ const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
338
+ this.h = h;
339
+ this.s = s;
340
+ this.v = v;
341
+ this.hexInput = rgbToHex(rgb);
342
+ this.hexInvalid = false;
343
+ }
344
+ connectedCallback() {
345
+ super.connectedCallback();
346
+ this.syncFromValue();
347
+ }
348
+ willUpdate(changed) {
349
+ if (changed.has("value")) this.syncFromValue();
350
+ }
351
+ disconnectedCallback() {
352
+ super.disconnectedCallback();
353
+ this.unbindGlobal();
354
+ this.unbindDrag();
355
+ }
356
+ bindGlobal() {
357
+ document.addEventListener("click", this.onDocClick, true);
358
+ document.addEventListener("keydown", this.onKeydown);
359
+ }
360
+ unbindGlobal() {
361
+ document.removeEventListener("click", this.onDocClick, true);
362
+ document.removeEventListener("keydown", this.onKeydown);
363
+ }
364
+ toggle() {
365
+ this.open ? this.close() : this.openPanel();
366
+ }
367
+ openPanel() {
368
+ if (this.open) return;
369
+ this.syncFromValue();
370
+ this.open = true;
371
+ this.bindGlobal();
372
+ this.dispatchEvent(
373
+ new CustomEvent("ok-open", { detail: { open: true }, bubbles: true, composed: true })
374
+ );
375
+ }
376
+ close() {
377
+ if (!this.open) return;
378
+ this.open = false;
379
+ this.unbindGlobal();
380
+ this.unbindDrag();
381
+ this.dispatchEvent(
382
+ new CustomEvent("ok-open", { detail: { open: false }, bubbles: true, composed: true })
383
+ );
384
+ }
385
+ // --- Emisión del color resultante ---
386
+ // Deriva el RGB/hex actual desde el HSV interno, actualiza `value` y emite `ok-change`.
387
+ commitFromHsv() {
388
+ const rgb = hsvToRgb(this.h, this.s, this.v);
389
+ const hex = rgbToHex(rgb);
390
+ this.value = hex;
391
+ this.hexInput = hex;
392
+ this.hexInvalid = false;
393
+ this.emit(hex, rgb);
394
+ }
395
+ emit(hex, rgb) {
396
+ this.dispatchEvent(
397
+ new CustomEvent("ok-change", {
398
+ detail: { value: hex, rgb },
399
+ bubbles: true,
400
+ composed: true
401
+ })
402
+ );
403
+ }
404
+ // --- Área Saturación/Valor (arrastre con pointer events) ---
405
+ // Calcula S y V a partir de la posición del puntero dentro del área.
406
+ updateSvFromPointer(clientX, clientY) {
407
+ const area = this.renderRoot.querySelector(".sv");
408
+ if (!area) return;
409
+ const rect = area.getBoundingClientRect();
410
+ this.s = clamp((clientX - rect.left) / rect.width, 0, 1);
411
+ this.v = clamp(1 - (clientY - rect.top) / rect.height, 0, 1);
412
+ this.commitFromHsv();
413
+ }
414
+ // Calcula el tono a partir de la posición X del puntero en la barra arcoíris.
415
+ updateHueFromPointer(clientX) {
416
+ const bar = this.renderRoot.querySelector(".hue");
417
+ if (!bar) return;
418
+ const rect = bar.getBoundingClientRect();
419
+ this.h = clamp((clientX - rect.left) / rect.width, 0, 1) * 360;
420
+ this.commitFromHsv();
421
+ }
422
+ bindDrag(kind) {
423
+ this.dragging = kind;
424
+ document.addEventListener("pointermove", this.onPointerMove);
425
+ document.addEventListener("pointerup", this.onPointerUp);
426
+ }
427
+ unbindDrag() {
428
+ this.dragging = null;
429
+ document.removeEventListener("pointermove", this.onPointerMove);
430
+ document.removeEventListener("pointerup", this.onPointerUp);
431
+ }
432
+ onSvPointerDown(e) {
433
+ e.preventDefault();
434
+ this.bindDrag("sv");
435
+ this.updateSvFromPointer(e.clientX, e.clientY);
436
+ }
437
+ onHuePointerDown(e) {
438
+ e.preventDefault();
439
+ this.bindDrag("hue");
440
+ this.updateHueFromPointer(e.clientX);
441
+ }
442
+ // --- Input hex ---
443
+ // Maneja la edición del input hex: valida y, si es correcto, deriva el HSV y emite.
444
+ onHexInput(raw) {
445
+ this.hexInput = raw;
446
+ const norm = normalizeHex(raw);
447
+ if (!norm) {
448
+ this.hexInvalid = true;
449
+ return;
450
+ }
451
+ this.hexInvalid = false;
452
+ const rgb = hexToRgb(norm);
453
+ const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
454
+ this.h = h;
455
+ this.s = s;
456
+ this.v = v;
457
+ this.value = norm;
458
+ this.emit(norm, rgb);
459
+ }
460
+ // --- Presets ---
461
+ // Selecciona un swatch preset: deriva HSV/hex y emite.
462
+ selectPreset(hex) {
463
+ const norm = normalizeHex(hex);
464
+ if (!norm) return;
465
+ const rgb = hexToRgb(norm);
466
+ const { h, s, v } = rgbToHsv(rgb.r, rgb.g, rgb.b);
467
+ this.h = h;
468
+ this.s = s;
469
+ this.v = v;
470
+ this.value = norm;
471
+ this.hexInput = norm;
472
+ this.hexInvalid = false;
473
+ this.emit(norm, rgb);
474
+ }
475
+ render() {
476
+ const hueColor = rgbToHex(hsvToRgb(this.h, 1, 1));
477
+ const current = rgbToHex(hsvToRgb(this.h, this.s, this.v));
478
+ const svLeft = `${this.s * 100}%`;
479
+ const svTop = `${(1 - this.v) * 100}%`;
480
+ const hueLeft = `${this.h / 360 * 100}%`;
481
+ return html`
482
+ <button
483
+ type="button"
484
+ class="swatch"
485
+ aria-haspopup="dialog"
486
+ aria-expanded=${this.open ? "true" : "false"}
487
+ aria-label=${this.t.triggerLabel}
488
+ @click=${() => this.toggle()}
489
+ >
490
+ <span class="fill" style=${`background:${this.value}`}></span>
491
+ </button>
492
+ ${this.open ? html`<div
493
+ class="panel"
494
+ role="dialog"
495
+ aria-label=${this.t.panelLabel}
496
+ style=${`--hue-color:${hueColor}`}
497
+ >
498
+ <div
499
+ class="sv"
500
+ @pointerdown=${(e) => this.onSvPointerDown(e)}
501
+ >
502
+ <span class="thumb" style=${`left:${svLeft};top:${svTop}`}></span>
503
+ </div>
504
+ <div
505
+ class="hue"
506
+ @pointerdown=${(e) => this.onHuePointerDown(e)}
507
+ >
508
+ <span class="thumb" style=${`left:${hueLeft}`}></span>
509
+ </div>
510
+ <div class="hexrow">
511
+ <span class="preview" style=${`background:${current}`}></span>
512
+ <input
513
+ class=${`hex ${this.hexInvalid ? "invalid" : ""}`.trim()}
514
+ type="text"
515
+ spellcheck="false"
516
+ autocomplete="off"
517
+ aria-label=${this.t.hexLabel}
518
+ .value=${this.hexInput}
519
+ @input=${(e) => this.onHexInput(e.target.value)}
520
+ />
521
+ </div>
522
+ ${this.presets.length ? html`<div class="presets">
523
+ ${this.presets.map((hex) => {
524
+ const norm = normalizeHex(hex);
525
+ const active = norm !== null && norm === this.value.toLowerCase();
526
+ return html`<button
527
+ type="button"
528
+ class=${active ? "active" : ""}
529
+ style=${`background:${hex}`}
530
+ aria-label=${hex}
531
+ @click=${() => this.selectPreset(hex)}
532
+ ></button>`;
533
+ })}
534
+ </div>` : ""}
535
+ </div>` : ""}
536
+ `;
537
+ }
538
+ }
539
+ __decorateClass([
540
+ property({ type: String })
541
+ ], OkColorPicker.prototype, "value");
542
+ __decorateClass([
543
+ property({ attribute: false })
544
+ ], OkColorPicker.prototype, "presets");
545
+ __decorateClass([
546
+ property({ attribute: false })
547
+ ], OkColorPicker.prototype, "labels");
548
+ __decorateClass([
549
+ state()
550
+ ], OkColorPicker.prototype, "open");
551
+ __decorateClass([
552
+ state()
553
+ ], OkColorPicker.prototype, "h");
554
+ __decorateClass([
555
+ state()
556
+ ], OkColorPicker.prototype, "s");
557
+ __decorateClass([
558
+ state()
559
+ ], OkColorPicker.prototype, "v");
560
+ __decorateClass([
561
+ state()
562
+ ], OkColorPicker.prototype, "hexInput");
563
+ __decorateClass([
564
+ state()
565
+ ], OkColorPicker.prototype, "hexInvalid");
566
+ define("ok-color-picker", OkColorPicker);
567
+ export {
568
+ OkColorPicker
569
+ };