@wrrdev/fenix-ui 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 (247) hide show
  1. package/README.md +117 -0
  2. package/dist/cdn.d.ts +6 -0
  3. package/dist/cdn.d.ts.map +1 -0
  4. package/dist/components/alert/alert.d.ts +14 -0
  5. package/dist/components/alert/alert.d.ts.map +1 -0
  6. package/dist/components/alert/alert.js +74 -0
  7. package/dist/components/alert/alert.js.map +1 -0
  8. package/dist/components/alert/index.d.ts +8 -0
  9. package/dist/components/alert/index.d.ts.map +1 -0
  10. package/dist/components/alert/index.js +7 -0
  11. package/dist/components/alert/index.js.map +1 -0
  12. package/dist/components/autocomplete/autocomplete.d.ts +20 -0
  13. package/dist/components/autocomplete/autocomplete.d.ts.map +1 -0
  14. package/dist/components/autocomplete/autocomplete.js +144 -0
  15. package/dist/components/autocomplete/autocomplete.js.map +1 -0
  16. package/dist/components/autocomplete/index.d.ts +8 -0
  17. package/dist/components/autocomplete/index.d.ts.map +1 -0
  18. package/dist/components/autocomplete/index.js +7 -0
  19. package/dist/components/autocomplete/index.js.map +1 -0
  20. package/dist/components/badge/badge.d.ts +14 -0
  21. package/dist/components/badge/badge.d.ts.map +1 -0
  22. package/dist/components/badge/badge.js +46 -0
  23. package/dist/components/badge/badge.js.map +1 -0
  24. package/dist/components/badge/index.d.ts +2 -0
  25. package/dist/components/badge/index.d.ts.map +1 -0
  26. package/dist/components/badge/index.js +7 -0
  27. package/dist/components/badge/index.js.map +1 -0
  28. package/dist/components/button/button.d.ts +30 -0
  29. package/dist/components/button/button.d.ts.map +1 -0
  30. package/dist/components/button/button.js +194 -0
  31. package/dist/components/button/button.js.map +1 -0
  32. package/dist/components/button/index.d.ts +2 -0
  33. package/dist/components/button/index.d.ts.map +1 -0
  34. package/dist/components/button/index.js +7 -0
  35. package/dist/components/button/index.js.map +1 -0
  36. package/dist/components/calendar/calendar.d.ts +39 -0
  37. package/dist/components/calendar/calendar.d.ts.map +1 -0
  38. package/dist/components/calendar/calendar.js +346 -0
  39. package/dist/components/calendar/calendar.js.map +1 -0
  40. package/dist/components/calendar/index.d.ts +2 -0
  41. package/dist/components/calendar/index.d.ts.map +1 -0
  42. package/dist/components/calendar/index.js +7 -0
  43. package/dist/components/calendar/index.js.map +1 -0
  44. package/dist/components/checkbox/checkbox.d.ts +24 -0
  45. package/dist/components/checkbox/checkbox.d.ts.map +1 -0
  46. package/dist/components/checkbox/checkbox.js +142 -0
  47. package/dist/components/checkbox/checkbox.js.map +1 -0
  48. package/dist/components/checkbox/index.d.ts +2 -0
  49. package/dist/components/checkbox/index.d.ts.map +1 -0
  50. package/dist/components/checkbox/index.js +7 -0
  51. package/dist/components/checkbox/index.js.map +1 -0
  52. package/dist/components/datepicker/datepicker.d.ts +62 -0
  53. package/dist/components/datepicker/datepicker.d.ts.map +1 -0
  54. package/dist/components/datepicker/datepicker.js +441 -0
  55. package/dist/components/datepicker/datepicker.js.map +1 -0
  56. package/dist/components/datepicker/index.d.ts +3 -0
  57. package/dist/components/datepicker/index.d.ts.map +1 -0
  58. package/dist/components/datepicker/index.js +8 -0
  59. package/dist/components/datepicker/index.js.map +1 -0
  60. package/dist/components/dialog/dialog.d.ts +19 -0
  61. package/dist/components/dialog/dialog.d.ts.map +1 -0
  62. package/dist/components/dialog/dialog.js +134 -0
  63. package/dist/components/dialog/dialog.js.map +1 -0
  64. package/dist/components/dialog/index.d.ts +8 -0
  65. package/dist/components/dialog/index.d.ts.map +1 -0
  66. package/dist/components/dialog/index.js +7 -0
  67. package/dist/components/dialog/index.js.map +1 -0
  68. package/dist/components/drawer/drawer.d.ts +27 -0
  69. package/dist/components/drawer/drawer.d.ts.map +1 -0
  70. package/dist/components/drawer/drawer.js +195 -0
  71. package/dist/components/drawer/drawer.js.map +1 -0
  72. package/dist/components/drawer/index.d.ts +8 -0
  73. package/dist/components/drawer/index.d.ts.map +1 -0
  74. package/dist/components/drawer/index.js +7 -0
  75. package/dist/components/drawer/index.js.map +1 -0
  76. package/dist/components/dropdown/dropdown.d.ts +28 -0
  77. package/dist/components/dropdown/dropdown.d.ts.map +1 -0
  78. package/dist/components/dropdown/dropdown.js +137 -0
  79. package/dist/components/dropdown/dropdown.js.map +1 -0
  80. package/dist/components/dropdown/index.d.ts +9 -0
  81. package/dist/components/dropdown/index.d.ts.map +1 -0
  82. package/dist/components/dropdown/index.js +9 -0
  83. package/dist/components/dropdown/index.js.map +1 -0
  84. package/dist/components/floatlabel/floatlabel.d.ts +42 -0
  85. package/dist/components/floatlabel/floatlabel.d.ts.map +1 -0
  86. package/dist/components/floatlabel/floatlabel.js +270 -0
  87. package/dist/components/floatlabel/floatlabel.js.map +1 -0
  88. package/dist/components/floatlabel/index.d.ts +2 -0
  89. package/dist/components/floatlabel/index.d.ts.map +1 -0
  90. package/dist/components/floatlabel/index.js +7 -0
  91. package/dist/components/floatlabel/index.js.map +1 -0
  92. package/dist/components/input/index.d.ts +2 -0
  93. package/dist/components/input/index.d.ts.map +1 -0
  94. package/dist/components/input/index.js +7 -0
  95. package/dist/components/input/index.js.map +1 -0
  96. package/dist/components/input/input.d.ts +22 -0
  97. package/dist/components/input/input.d.ts.map +1 -0
  98. package/dist/components/input/input.js +169 -0
  99. package/dist/components/input/input.js.map +1 -0
  100. package/dist/components/multiselect/index.d.ts +2 -0
  101. package/dist/components/multiselect/index.d.ts.map +1 -0
  102. package/dist/components/multiselect/index.js +7 -0
  103. package/dist/components/multiselect/index.js.map +1 -0
  104. package/dist/components/multiselect/multiselect.d.ts +32 -0
  105. package/dist/components/multiselect/multiselect.d.ts.map +1 -0
  106. package/dist/components/multiselect/multiselect.js +389 -0
  107. package/dist/components/multiselect/multiselect.js.map +1 -0
  108. package/dist/components/pagination/index.d.ts +8 -0
  109. package/dist/components/pagination/index.d.ts.map +1 -0
  110. package/dist/components/pagination/index.js +7 -0
  111. package/dist/components/pagination/index.js.map +1 -0
  112. package/dist/components/pagination/pagination.d.ts +23 -0
  113. package/dist/components/pagination/pagination.d.ts.map +1 -0
  114. package/dist/components/pagination/pagination.js +121 -0
  115. package/dist/components/pagination/pagination.js.map +1 -0
  116. package/dist/components/progress/index.d.ts +8 -0
  117. package/dist/components/progress/index.d.ts.map +1 -0
  118. package/dist/components/progress/index.js +7 -0
  119. package/dist/components/progress/index.js.map +1 -0
  120. package/dist/components/progress/progress.d.ts +18 -0
  121. package/dist/components/progress/progress.d.ts.map +1 -0
  122. package/dist/components/progress/progress.js +99 -0
  123. package/dist/components/progress/progress.js.map +1 -0
  124. package/dist/components/radio/index.d.ts +2 -0
  125. package/dist/components/radio/index.d.ts.map +1 -0
  126. package/dist/components/radio/index.js +7 -0
  127. package/dist/components/radio/index.js.map +1 -0
  128. package/dist/components/radio/radio.d.ts +23 -0
  129. package/dist/components/radio/radio.d.ts.map +1 -0
  130. package/dist/components/radio/radio.js +133 -0
  131. package/dist/components/radio/radio.js.map +1 -0
  132. package/dist/components/select/index.d.ts +2 -0
  133. package/dist/components/select/index.d.ts.map +1 -0
  134. package/dist/components/select/index.js +7 -0
  135. package/dist/components/select/index.js.map +1 -0
  136. package/dist/components/select/select.d.ts +36 -0
  137. package/dist/components/select/select.d.ts.map +1 -0
  138. package/dist/components/select/select.js +287 -0
  139. package/dist/components/select/select.js.map +1 -0
  140. package/dist/components/skeleton/index.d.ts +8 -0
  141. package/dist/components/skeleton/index.d.ts.map +1 -0
  142. package/dist/components/skeleton/index.js +7 -0
  143. package/dist/components/skeleton/index.js.map +1 -0
  144. package/dist/components/skeleton/skeleton.d.ts +13 -0
  145. package/dist/components/skeleton/skeleton.d.ts.map +1 -0
  146. package/dist/components/skeleton/skeleton.js +57 -0
  147. package/dist/components/skeleton/skeleton.js.map +1 -0
  148. package/dist/components/spinner/index.d.ts +2 -0
  149. package/dist/components/spinner/index.d.ts.map +1 -0
  150. package/dist/components/spinner/index.js +7 -0
  151. package/dist/components/spinner/index.js.map +1 -0
  152. package/dist/components/spinner/spinner.d.ts +16 -0
  153. package/dist/components/spinner/spinner.d.ts.map +1 -0
  154. package/dist/components/spinner/spinner.js +50 -0
  155. package/dist/components/spinner/spinner.js.map +1 -0
  156. package/dist/components/switch/index.d.ts +2 -0
  157. package/dist/components/switch/index.d.ts.map +1 -0
  158. package/dist/components/switch/index.js +7 -0
  159. package/dist/components/switch/index.js.map +1 -0
  160. package/dist/components/switch/switch.d.ts +22 -0
  161. package/dist/components/switch/switch.d.ts.map +1 -0
  162. package/dist/components/switch/switch.js +115 -0
  163. package/dist/components/switch/switch.js.map +1 -0
  164. package/dist/components/table/index.d.ts +2 -0
  165. package/dist/components/table/index.d.ts.map +1 -0
  166. package/dist/components/table/index.js +7 -0
  167. package/dist/components/table/index.js.map +1 -0
  168. package/dist/components/table/table.d.ts +38 -0
  169. package/dist/components/table/table.d.ts.map +1 -0
  170. package/dist/components/table/table.js +258 -0
  171. package/dist/components/table/table.js.map +1 -0
  172. package/dist/components/tabs/index.d.ts +9 -0
  173. package/dist/components/tabs/index.d.ts.map +1 -0
  174. package/dist/components/tabs/index.js +9 -0
  175. package/dist/components/tabs/index.js.map +1 -0
  176. package/dist/components/tabs/tabs.d.ts +38 -0
  177. package/dist/components/tabs/tabs.d.ts.map +1 -0
  178. package/dist/components/tabs/tabs.js +162 -0
  179. package/dist/components/tabs/tabs.js.map +1 -0
  180. package/dist/components/textarea/index.d.ts +8 -0
  181. package/dist/components/textarea/index.d.ts.map +1 -0
  182. package/dist/components/textarea/index.js +7 -0
  183. package/dist/components/textarea/index.js.map +1 -0
  184. package/dist/components/textarea/textarea.d.ts +19 -0
  185. package/dist/components/textarea/textarea.d.ts.map +1 -0
  186. package/dist/components/textarea/textarea.js +109 -0
  187. package/dist/components/textarea/textarea.js.map +1 -0
  188. package/dist/components/toast/index.d.ts +8 -0
  189. package/dist/components/toast/index.d.ts.map +1 -0
  190. package/dist/components/toast/index.js +8 -0
  191. package/dist/components/toast/index.js.map +1 -0
  192. package/dist/components/toast/toast.d.ts +40 -0
  193. package/dist/components/toast/toast.d.ts.map +1 -0
  194. package/dist/components/toast/toast.js +176 -0
  195. package/dist/components/toast/toast.js.map +1 -0
  196. package/dist/components/tooltip/index.d.ts +8 -0
  197. package/dist/components/tooltip/index.d.ts.map +1 -0
  198. package/dist/components/tooltip/index.js +7 -0
  199. package/dist/components/tooltip/index.js.map +1 -0
  200. package/dist/components/tooltip/tooltip.d.ts +14 -0
  201. package/dist/components/tooltip/tooltip.d.ts.map +1 -0
  202. package/dist/components/tooltip/tooltip.js +86 -0
  203. package/dist/components/tooltip/tooltip.js.map +1 -0
  204. package/dist/core/base.d.ts +29 -0
  205. package/dist/core/base.d.ts.map +1 -0
  206. package/dist/core/base.js +41 -0
  207. package/dist/core/base.js.map +1 -0
  208. package/dist/core/css.d.ts +6 -0
  209. package/dist/core/css.d.ts.map +1 -0
  210. package/dist/core/css.js +11 -0
  211. package/dist/core/css.js.map +1 -0
  212. package/dist/core/define.d.ts +8 -0
  213. package/dist/core/define.d.ts.map +1 -0
  214. package/dist/core/define.js +10 -0
  215. package/dist/core/define.js.map +1 -0
  216. package/dist/core/presets.d.ts +40 -0
  217. package/dist/core/presets.d.ts.map +1 -0
  218. package/dist/core/presets.js +80 -0
  219. package/dist/core/presets.js.map +1 -0
  220. package/dist/core/theme.d.ts +47 -0
  221. package/dist/core/theme.d.ts.map +1 -0
  222. package/dist/core/theme.js +76 -0
  223. package/dist/core/theme.js.map +1 -0
  224. package/dist/core/tokens.d.ts +36 -0
  225. package/dist/core/tokens.d.ts.map +1 -0
  226. package/dist/core/tokens.js +83 -0
  227. package/dist/core/tokens.js.map +1 -0
  228. package/dist/docs/app.d.ts +37 -0
  229. package/dist/docs/app.d.ts.map +1 -0
  230. package/dist/fenix-ui.esm.js +4471 -0
  231. package/dist/fenix-ui.esm.js.map +1 -0
  232. package/dist/fenix-ui.umd.min.js +2022 -0
  233. package/dist/fenix-ui2.esm.js +82 -0
  234. package/dist/fenix-ui2.esm.js.map +1 -0
  235. package/dist/index.d.ts +39 -0
  236. package/dist/index.d.ts.map +1 -0
  237. package/dist/index.js +107 -0
  238. package/dist/index.js.map +1 -0
  239. package/dist/plugins/auto-import.d.ts +18 -0
  240. package/dist/plugins/auto-import.d.ts.map +1 -0
  241. package/dist/plugins/auto-import.js +69 -0
  242. package/dist/plugins/auto-import.js.map +1 -0
  243. package/dist/plugins/index.d.ts +25 -0
  244. package/dist/plugins/index.d.ts.map +1 -0
  245. package/dist/plugins/index.js +21 -0
  246. package/dist/plugins/index.js.map +1 -0
  247. package/package.json +169 -0
@@ -0,0 +1,194 @@
1
+ import { FxElement } from "../../core/base.js";
2
+ import { css } from "../../core/css.js";
3
+ import { defineElement } from "../../core/define.js";
4
+ const _FxButton = class _FxButton extends FxElement {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.spawnRipple = (event) => {
8
+ if (this.hasAttr("disabled") || this.hasAttr("loading")) return;
9
+ const enabled = getComputedStyle(this).getPropertyValue("--fx-effect-ripple").trim();
10
+ if (enabled === "0" || enabled === "false") return;
11
+ const btn = this.root.querySelector(".btn");
12
+ if (!btn) return;
13
+ const rect = btn.getBoundingClientRect();
14
+ const size = Math.max(rect.width, rect.height);
15
+ const ripple = document.createElement("span");
16
+ ripple.className = "btn__ripple";
17
+ ripple.style.width = ripple.style.height = `${size}px`;
18
+ ripple.style.left = `${event.clientX - rect.left - size / 2}px`;
19
+ ripple.style.top = `${event.clientY - rect.top - size / 2}px`;
20
+ btn.appendChild(ripple);
21
+ ripple.addEventListener("animationend", () => ripple.remove());
22
+ };
23
+ }
24
+ static get observedAttributes() {
25
+ return ["variant", "size", "disabled", "loading", "type", "full"];
26
+ }
27
+ /** Tamanho. Padrão: `'md'`. */
28
+ get size() {
29
+ const s = this.getAttr("size", "md");
30
+ return s === "sm" || s === "lg" ? s : "md";
31
+ }
32
+ set size(value) {
33
+ this.setAttribute("size", value);
34
+ }
35
+ get disabled() {
36
+ return this.hasAttr("disabled");
37
+ }
38
+ set disabled(value) {
39
+ this.toggleAttr("disabled", Boolean(value));
40
+ }
41
+ get loading() {
42
+ return this.hasAttr("loading");
43
+ }
44
+ set loading(value) {
45
+ this.toggleAttr("loading", Boolean(value));
46
+ }
47
+ render() {
48
+ const loading = this.hasAttr("loading");
49
+ const disabled = this.hasAttr("disabled") || loading;
50
+ const btnType = this.getAttr("type", "button");
51
+ this.setTemplate(`
52
+ <button class="btn" part="button" type="${btnType}">
53
+ <span class="btn__icon" part="icon"><slot name="icon"></slot></span>
54
+ <span class="btn__label" part="label"><slot></slot></span>
55
+ ${loading ? '<span class="btn__spinner" aria-hidden="true"></span>' : ""}
56
+ </button>
57
+ `);
58
+ const btn = this.root.querySelector(".btn");
59
+ if (!btn) return;
60
+ const iconSlot = btn.querySelector(".btn__icon slot");
61
+ const iconWrap = this.root.querySelector(".btn__icon");
62
+ const hasIcon = Boolean(iconSlot?.assignedNodes({ flatten: true }).some(
63
+ (n) => n.nodeType === Node.ELEMENT_NODE || (n.textContent ?? "").trim() !== ""
64
+ ));
65
+ iconWrap?.toggleAttribute("hidden", !hasIcon);
66
+ if (disabled) {
67
+ btn.setAttribute("disabled", "");
68
+ btn.setAttribute("aria-disabled", "true");
69
+ } else {
70
+ btn.removeAttribute("disabled");
71
+ btn.removeAttribute("aria-disabled");
72
+ }
73
+ if (loading) btn.setAttribute("aria-busy", "true");
74
+ else btn.removeAttribute("aria-busy");
75
+ }
76
+ connectedCallback() {
77
+ super.connectedCallback();
78
+ this.addEventListener("pointerdown", this.spawnRipple);
79
+ }
80
+ disconnectedCallback() {
81
+ super.disconnectedCallback();
82
+ this.removeEventListener("pointerdown", this.spawnRipple);
83
+ }
84
+ };
85
+ _FxButton.styles = css`
86
+ :host {
87
+ display: inline-block;
88
+ vertical-align: middle;
89
+ }
90
+ .btn {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ text-align: center;
95
+ gap: var(--fx-space-sm);
96
+ font-family: var(--fx-font-family);
97
+ font-size: var(--fx-font-size);
98
+ font-weight: var(--fx-font-weight);
99
+ line-height: var(--fx-font-line-height);
100
+ padding: var(--fx-space-md) var(--fx-space-xl);
101
+ border-radius: var(--fx-radius-md);
102
+ border: 1px solid transparent;
103
+ color: #fff;
104
+ background: var(--fx-color-primary);
105
+ cursor: pointer;
106
+ user-select: none;
107
+ text-decoration: none;
108
+ transition:
109
+ background-color var(--fx-motion-duration-normal) var(--fx-motion-easing),
110
+ border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),
111
+ transform var(--fx-motion-duration-fast) var(--fx-motion-easing),
112
+ box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);
113
+ }
114
+ .btn:focus-visible {
115
+ outline: 2px solid var(--fx-color-primary);
116
+ outline-offset: 2px;
117
+ }
118
+ .btn:hover { filter: brightness(0.88); }
119
+ .btn:active { transform: translateY(1px); }
120
+
121
+ /* Tamanhos — alturas vindas dos tokens (personalizáveis por preset) */
122
+ .btn { min-height: var(--fx-size-md); }
123
+ :host([size='sm']) .btn { padding: var(--fx-space-sm) var(--fx-space-lg); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }
124
+ :host([size='lg']) .btn { padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }
125
+
126
+ /* Full width */
127
+ :host([full]) .btn { width: 100%; }
128
+
129
+ /* Variantes */
130
+ :host([variant='secondary']) .btn { background: var(--fx-color-secondary); }
131
+ :host([variant='success']) .btn { background: var(--fx-color-success); }
132
+ :host([variant='warning']) .btn { background: var(--fx-color-warning); }
133
+ :host([variant='danger']) .btn { background: var(--fx-color-danger); }
134
+ :host([variant='ghost']) .btn { background: transparent; color: var(--fx-text-default); }
135
+ :host([variant='ghost']) .btn:hover { background: var(--fx-surface-surface-hover); filter: none; }
136
+ :host([variant='outline']) .btn { background: transparent; color: var(--fx-color-primary); border-color: var(--fx-color-primary); }
137
+ :host([variant='outline']) .btn:hover { background: var(--fx-surface-surface-hover); filter: none; }
138
+
139
+ /* Ícone e spinner */
140
+ .btn__icon { display: inline-flex; }
141
+ .btn__icon[hidden] { display: none; }
142
+ .btn__label { display: inline-flex; align-items: center; justify-content: center; }
143
+ .btn[hidden] { display: none; }
144
+ .btn__spinner {
145
+ width: 1em;
146
+ height: 1em;
147
+ border: 2px solid currentColor;
148
+ border-top-color: transparent;
149
+ border-radius: var(--fx-radius-full);
150
+ animation: fx-spin var(--fx-motion-duration-normal) linear infinite;
151
+ }
152
+ @keyframes fx-spin { to { transform: rotate(360deg); } }
153
+
154
+ /* Estados */
155
+ :host([disabled]) .btn,
156
+ :host([loading]) .btn {
157
+ opacity: 0.55;
158
+ cursor: not-allowed;
159
+ pointer-events: none;
160
+ }
161
+
162
+ /* Efeito ripple (). Desative com effect.ripple: '0' no preset. */
163
+ .btn {
164
+ position: relative;
165
+ overflow: hidden;
166
+ }
167
+ .btn__ripple {
168
+ position: absolute;
169
+ border-radius: var(--fx-radius-full);
170
+ background: currentColor;
171
+ opacity: 0.28;
172
+ transform: scale(0);
173
+ animation: fx-ripple 600ms var(--fx-motion-easing) forwards;
174
+ pointer-events: none;
175
+ }
176
+ @keyframes fx-ripple {
177
+ to {
178
+ transform: scale(2.6);
179
+ opacity: 0;
180
+ }
181
+ }
182
+ @media (prefers-reduced-motion: reduce) {
183
+ .btn__ripple { display: none; }
184
+ }
185
+ `;
186
+ let FxButton = _FxButton;
187
+ function defineFxButton() {
188
+ return defineElement("fx-button", FxButton);
189
+ }
190
+ export {
191
+ FxButton,
192
+ defineFxButton
193
+ };
194
+ //# sourceMappingURL=button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.js","sources":["../../../src/components/button/button.ts"],"sourcesContent":["import { FxElement } from '../../core/base';\nimport { css } from '../../core/css';\nimport { defineElement } from '../../core/define';\n\n/**\n * <fx-button> — Componente de ação (piloto).\n *\n * Atributos: variant, size, disabled, loading, type, full.\n * Slots: default (rótulo), `icon` (ícone opcional).\n * Evento: `click` nativo atravessa o Shadow DOM (composed) — ouça no host.\n */\nexport class FxButton extends FxElement {\n static override styles = css`\n :host {\n display: inline-block;\n vertical-align: middle;\n }\n .btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n gap: var(--fx-space-sm);\n font-family: var(--fx-font-family);\n font-size: var(--fx-font-size);\n font-weight: var(--fx-font-weight);\n line-height: var(--fx-font-line-height);\n padding: var(--fx-space-md) var(--fx-space-xl);\n border-radius: var(--fx-radius-md);\n border: 1px solid transparent;\n color: #fff;\n background: var(--fx-color-primary);\n cursor: pointer;\n user-select: none;\n text-decoration: none;\n transition:\n background-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n border-color var(--fx-motion-duration-normal) var(--fx-motion-easing),\n transform var(--fx-motion-duration-fast) var(--fx-motion-easing),\n box-shadow var(--fx-motion-duration-normal) var(--fx-motion-easing);\n }\n .btn:focus-visible {\n outline: 2px solid var(--fx-color-primary);\n outline-offset: 2px;\n }\n .btn:hover { filter: brightness(0.88); }\n .btn:active { transform: translateY(1px); }\n\n /* Tamanhos — alturas vindas dos tokens (personalizáveis por preset) */\n .btn { min-height: var(--fx-size-md); }\n :host([size='sm']) .btn { padding: var(--fx-space-sm) var(--fx-space-lg); font-size: var(--fx-font-size); min-height: var(--fx-size-sm); }\n :host([size='lg']) .btn { padding: var(--fx-space-lg) var(--fx-space-xl); font-size: calc(var(--fx-font-size) + 4px); min-height: var(--fx-size-lg); }\n\n /* Full width */\n :host([full]) .btn { width: 100%; }\n\n /* Variantes */\n :host([variant='secondary']) .btn { background: var(--fx-color-secondary); }\n :host([variant='success']) .btn { background: var(--fx-color-success); }\n :host([variant='warning']) .btn { background: var(--fx-color-warning); }\n :host([variant='danger']) .btn { background: var(--fx-color-danger); }\n :host([variant='ghost']) .btn { background: transparent; color: var(--fx-text-default); }\n :host([variant='ghost']) .btn:hover { background: var(--fx-surface-surface-hover); filter: none; }\n :host([variant='outline']) .btn { background: transparent; color: var(--fx-color-primary); border-color: var(--fx-color-primary); }\n :host([variant='outline']) .btn:hover { background: var(--fx-surface-surface-hover); filter: none; }\n\n /* Ícone e spinner */\n .btn__icon { display: inline-flex; }\n .btn__icon[hidden] { display: none; }\n .btn__label { display: inline-flex; align-items: center; justify-content: center; }\n .btn[hidden] { display: none; }\n .btn__spinner {\n width: 1em;\n height: 1em;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: var(--fx-radius-full);\n animation: fx-spin var(--fx-motion-duration-normal) linear infinite;\n }\n @keyframes fx-spin { to { transform: rotate(360deg); } }\n\n /* Estados */\n :host([disabled]) .btn,\n :host([loading]) .btn {\n opacity: 0.55;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* Efeito ripple (). Desative com effect.ripple: '0' no preset. */\n .btn {\n position: relative;\n overflow: hidden;\n }\n .btn__ripple {\n position: absolute;\n border-radius: var(--fx-radius-full);\n background: currentColor;\n opacity: 0.28;\n transform: scale(0);\n animation: fx-ripple 600ms var(--fx-motion-easing) forwards;\n pointer-events: none;\n }\n @keyframes fx-ripple {\n to {\n transform: scale(2.6);\n opacity: 0;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .btn__ripple { display: none; }\n }\n `;\n\n static override get observedAttributes(): string[] {\n return ['variant', 'size', 'disabled', 'loading', 'type', 'full'];\n }\n\n /** Tamanho. Padrão: `'md'`. */\n get size(): string {\n const s = this.getAttr('size', 'md');\n return s === 'sm' || s === 'lg' ? s : 'md';\n }\n set size(value: string) {\n this.setAttribute('size', value);\n }\n\n get disabled(): boolean {\n return this.hasAttr('disabled');\n }\n set disabled(value: boolean) {\n this.toggleAttr('disabled', Boolean(value));\n }\n\n get loading(): boolean {\n return this.hasAttr('loading');\n }\n set loading(value: boolean) {\n this.toggleAttr('loading', Boolean(value));\n }\n\n protected override render(): void {\n const loading = this.hasAttr('loading');\n const disabled = this.hasAttr('disabled') || loading;\n const btnType = this.getAttr('type', 'button');\n\n this.setTemplate(`\n <button class=\"btn\" part=\"button\" type=\"${btnType}\">\n <span class=\"btn__icon\" part=\"icon\"><slot name=\"icon\"></slot></span>\n <span class=\"btn__label\" part=\"label\"><slot></slot></span>\n ${loading ? '<span class=\"btn__spinner\" aria-hidden=\"true\"></span>' : ''}\n </button>\n `);\n\n const btn = this.root.querySelector<HTMLButtonElement>('.btn');\n if (!btn) return;\n\n // Esconde o container do ícone quando o slot está vazio,\n // evitando espaço fantasma do `gap` que descentraliza o rótulo.\n const iconSlot = btn.querySelector<HTMLSlotElement>('.btn__icon slot');\n const iconWrap = this.root.querySelector<HTMLElement>('.btn__icon');\n const hasIcon = Boolean(iconSlot?.assignedNodes({ flatten: true }).some((n) =>\n n.nodeType === Node.ELEMENT_NODE || (n.textContent ?? '').trim() !== '',\n ));\n iconWrap?.toggleAttribute('hidden', !hasIcon);\n if (disabled) {\n btn.setAttribute('disabled', '');\n btn.setAttribute('aria-disabled', 'true');\n } else {\n btn.removeAttribute('disabled');\n btn.removeAttribute('aria-disabled');\n }\n if (loading) btn.setAttribute('aria-busy', 'true');\n else btn.removeAttribute('aria-busy');\n }\n\n protected override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('pointerdown', this.spawnRipple);\n }\n\n protected override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('pointerdown', this.spawnRipple);\n }\n\n /**\n * Efeito ripple : cria um círculo que expande do ponto\n * de clique e desaparece. Respeita o token `effect.ripple` ('0' desativa)\n * e `prefers-reduced-motion` (via CSS).\n */\n private spawnRipple = (event: PointerEvent): void => {\n if (this.hasAttr('disabled') || this.hasAttr('loading')) return;\n const enabled = getComputedStyle(this)\n .getPropertyValue('--fx-effect-ripple')\n .trim();\n if (enabled === '0' || enabled === 'false') return;\n\n const btn = this.root.querySelector<HTMLElement>('.btn');\n if (!btn) return;\n\n const rect = btn.getBoundingClientRect();\n const size = Math.max(rect.width, rect.height);\n const ripple = document.createElement('span');\n ripple.className = 'btn__ripple';\n ripple.style.width = ripple.style.height = `${size}px`;\n ripple.style.left = `${event.clientX - rect.left - size / 2}px`;\n ripple.style.top = `${event.clientY - rect.top - size / 2}px`;\n btn.appendChild(ripple);\n ripple.addEventListener('animationend', () => ripple.remove());\n };\n}\n\nexport function defineFxButton(): typeof FxButton {\n return defineElement('fx-button', FxButton);\n}"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { FxButton } from './button';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { defineFxButton } from "./button.js";
2
+ import { FxButton } from "./button.js";
3
+ defineFxButton();
4
+ export {
5
+ FxButton
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/button/index.ts"],"sourcesContent":["import { defineFxButton } from './button';\n\n// Reexporta a classe para uso programático (ex.: instanceof, herança).\nexport { FxButton } from './button';\n\n// Auto-registro: basta importar o subpath `@wrrdev/fenix-ui/button`\n// para que o componente seja definido no CustomElementRegistry.\ndefineFxButton();"],"names":[],"mappings":";;AAOA,eAAA;"}
@@ -0,0 +1,39 @@
1
+ import { FxElement } from '../../core/base';
2
+ export declare class FxCalendar extends FxElement {
3
+ static styles: string;
4
+ static get observedAttributes(): string[];
5
+ private view;
6
+ private cursor;
7
+ /** Período em construção (chaves numéricas). */
8
+ private pickStart;
9
+ private pickEnd;
10
+ /** Modo de seleção: 'single' | 'range' | 'multiple'. */
11
+ get mode(): 'single' | 'range' | 'multiple';
12
+ set mode(m: 'single' | 'range' | 'multiple');
13
+ get range(): boolean;
14
+ set range(value: boolean);
15
+ /** Datas selecionadas no modo multiple (CSV no atributo). */
16
+ get values(): string[];
17
+ set values(list: string[]);
18
+ get value(): string;
19
+ set value(v: string);
20
+ private bounds;
21
+ private locale;
22
+ private fmt;
23
+ private dayDisabled;
24
+ private monthDisabled;
25
+ private yearDisabled;
26
+ private dayKeyOf;
27
+ private keyToDate;
28
+ private iso;
29
+ /** Seleção atual para pintura (chaves). */
30
+ private selection;
31
+ private emit;
32
+ private pickDay;
33
+ private navigate;
34
+ protected render(): void;
35
+ /** Grade de dias com preenchimento do mês anterior. */
36
+ private daysHtml;
37
+ }
38
+ export declare function defineFxCalendar(): typeof FxCalendar;
39
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../../src/components/calendar/calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAyC5C,qBAAa,UAAW,SAAQ,SAAS;IACvC,OAAgB,MAAM,SAkFpB;IAEF,WAAoB,kBAAkB,IAAI,MAAM,EAAE,CAEjD;IAED,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,MAAM,CAA6D;IAC3E,gDAAgD;IAChD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IAEtC,wDAAwD;IACxD,IAAI,IAAI,IAAI,QAAQ,GAAG,OAAO,GAAG,UAAU,CAI1C;IACD,IAAI,IAAI,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,EAE1C;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAED,6DAA6D;IAC7D,IAAI,MAAM,IAAI,MAAM,EAAE,CAGrB;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAExB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,EAElB;IAED,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,GAAG;IAQX,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;IAMX,2CAA2C;IAC3C,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,IAAI;IAkBZ,OAAO,CAAC,OAAO;IA2Bf,OAAO,CAAC,QAAQ;cAYG,MAAM,IAAI,IAAI;IAiFjC,uDAAuD;IACvD,OAAO,CAAC,QAAQ;CAuBjB;AAED,wBAAgB,gBAAgB,IAAI,OAAO,UAAU,CAEpD"}
@@ -0,0 +1,346 @@
1
+ import { FxElement } from "../../core/base.js";
2
+ import { css } from "../../core/css.js";
3
+ import { defineElement } from "../../core/define.js";
4
+ const key = (y, m1, d) => y * 1e4 + m1 * 100 + d;
5
+ function parseBound(raw) {
6
+ const m = /^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?$/.exec(raw.trim());
7
+ if (!m) return null;
8
+ const y = +m[1];
9
+ const m1 = m[2] ? +m[2] : 1;
10
+ const d = m[3] ? +m[3] : null;
11
+ if (d !== null) return { lo: key(y, m1, d), hi: key(y, m1, d) };
12
+ if (m[2]) return { lo: key(y, m1, 1), hi: key(y, m1, 31) };
13
+ return { lo: key(y, 1, 1), hi: key(y, 12, 31) };
14
+ }
15
+ const _FxCalendar = class _FxCalendar extends FxElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.view = "days";
19
+ this.cursor = { y: (/* @__PURE__ */ new Date()).getFullYear(), m: (/* @__PURE__ */ new Date()).getMonth() };
20
+ this.pickStart = null;
21
+ this.pickEnd = null;
22
+ }
23
+ static get observedAttributes() {
24
+ return ["value", "start", "end", "min", "max", "range", "mode", "values", "locale", "disabled"];
25
+ }
26
+ /** Modo de seleção: 'single' | 'range' | 'multiple'. */
27
+ get mode() {
28
+ const m = this.getAttr("mode");
29
+ if (m === "range" || m === "multiple") return m;
30
+ return this.hasAttr("range") ? "range" : "single";
31
+ }
32
+ set mode(m) {
33
+ this.setAttribute("mode", m);
34
+ }
35
+ get range() {
36
+ return this.mode === "range";
37
+ }
38
+ set range(value) {
39
+ this.toggleAttr("range", Boolean(value));
40
+ }
41
+ /** Datas selecionadas no modo multiple (CSV no atributo). */
42
+ get values() {
43
+ const csv = this.getAttr("values");
44
+ return csv ? csv.split(",").map((v) => v.trim()).filter(Boolean) : [];
45
+ }
46
+ set values(list) {
47
+ this.setAttribute("values", list.join(","));
48
+ }
49
+ get value() {
50
+ return this.getAttr("value");
51
+ }
52
+ set value(v) {
53
+ this.setAttribute("value", v);
54
+ }
55
+ bounds() {
56
+ return {
57
+ min: parseBound(this.getAttr("min", "")),
58
+ max: parseBound(this.getAttr("max", ""))
59
+ };
60
+ }
61
+ locale() {
62
+ return this.getAttr("locale", "pt-BR");
63
+ }
64
+ fmt(opts, d) {
65
+ try {
66
+ return new Intl.DateTimeFormat(this.locale(), opts).format(d);
67
+ } catch {
68
+ return new Intl.DateTimeFormat("pt-BR", opts).format(d);
69
+ }
70
+ }
71
+ dayDisabled(y, m, d) {
72
+ const { min, max } = this.bounds();
73
+ const k = key(y, m + 1, d);
74
+ return min !== null && k < min.lo || max !== null && k > max.hi;
75
+ }
76
+ monthDisabled(y, m1) {
77
+ const { min, max } = this.bounds();
78
+ const lo = key(y, m1, 1);
79
+ const hi = key(y, m1, 31);
80
+ return min !== null && hi < min.lo || max !== null && lo > max.hi;
81
+ }
82
+ yearDisabled(y) {
83
+ const { min, max } = this.bounds();
84
+ const lo = key(y, 1, 1);
85
+ const hi = key(y, 12, 31);
86
+ return min !== null && hi < min.lo || max !== null && lo > max.hi;
87
+ }
88
+ dayKeyOf(date) {
89
+ return key(date.getFullYear(), date.getMonth() + 1, date.getDate());
90
+ }
91
+ keyToDate(k) {
92
+ return new Date(Math.floor(k / 1e4), Math.floor(k / 100) % 100 - 1, k % 100);
93
+ }
94
+ iso(k) {
95
+ const d = this.keyToDate(k);
96
+ const p = (n) => String(n).padStart(2, "0");
97
+ return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
98
+ }
99
+ /** Seleção atual para pintura (chaves). */
100
+ selection() {
101
+ const multi = new Set(this.values.map((iso) => parseBound(iso)?.lo ?? 0).filter(Boolean));
102
+ if (this.mode === "range") {
103
+ let s = this.pickStart;
104
+ let e = this.pickEnd;
105
+ const attrS = parseBound(this.getAttr("start", ""));
106
+ const attrE = parseBound(this.getAttr("end", ""));
107
+ if (s === null && attrS) s = attrS.lo;
108
+ if (e === null && attrE) e = attrE.lo;
109
+ return { start: s, end: e, single: null, multi };
110
+ }
111
+ if (this.mode === "multiple") {
112
+ return { start: null, end: null, single: null, multi };
113
+ }
114
+ const v = parseBound(this.getAttr("value", ""));
115
+ return { start: null, end: null, single: v ? v.lo : null, multi };
116
+ }
117
+ emit() {
118
+ if (this.mode === "range") {
119
+ const detail = {
120
+ start: this.pickStart !== null ? this.iso(this.pickStart) : this.getAttr("start", ""),
121
+ end: this.pickEnd !== null ? this.iso(this.pickEnd) : this.getAttr("end", "")
122
+ };
123
+ this.setAttribute("start", detail.start);
124
+ this.setAttribute("end", detail.end);
125
+ this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail }));
126
+ } else if (this.mode === "multiple") {
127
+ const values = this.values;
128
+ this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail: { values } }));
129
+ } else {
130
+ const value = this.getAttr("value");
131
+ this.dispatchEvent(new CustomEvent("change", { bubbles: true, composed: true, detail: { value } }));
132
+ }
133
+ }
134
+ pickDay(k) {
135
+ if (this.mode === "range") {
136
+ if (this.pickStart === null || this.pickEnd !== null) {
137
+ this.pickStart = k;
138
+ this.pickEnd = null;
139
+ this.setAttribute("start", this.iso(k));
140
+ this.removeAttribute("end");
141
+ this.render();
142
+ return;
143
+ }
144
+ if (k < this.pickStart) [this.pickStart, this.pickEnd] = [k, this.pickStart];
145
+ else this.pickEnd = k;
146
+ this.emit();
147
+ } else if (this.mode === "multiple") {
148
+ const set = new Set(this.values);
149
+ const iso = this.iso(k);
150
+ if (set.has(iso)) set.delete(iso);
151
+ else set.add(iso);
152
+ this.values = [...set].sort();
153
+ this.emit();
154
+ } else {
155
+ this.value = this.iso(k);
156
+ this.emit();
157
+ }
158
+ this.render();
159
+ }
160
+ navigate(dir) {
161
+ if (this.view === "days") {
162
+ const d = new Date(this.cursor.y, this.cursor.m + dir, 1);
163
+ this.cursor = { y: d.getFullYear(), m: d.getMonth() };
164
+ } else if (this.view === "months") {
165
+ this.cursor.y += dir;
166
+ } else {
167
+ this.cursor.y += dir * 12;
168
+ }
169
+ this.render();
170
+ }
171
+ render() {
172
+ const todayK = this.dayKeyOf(/* @__PURE__ */ new Date());
173
+ const sel = this.selection();
174
+ const loc = this.locale();
175
+ const titles = {
176
+ days: this.fmt({ month: "long", year: "numeric" }, new Date(this.cursor.y, this.cursor.m, 1)),
177
+ months: String(this.cursor.y),
178
+ years: `${Math.floor(this.cursor.y / 12) * 12} – ${Math.floor(this.cursor.y / 12) * 12 + 11}`
179
+ };
180
+ let cells = "";
181
+ if (this.view === "days") {
182
+ const wds = [...Array(7)].map(
183
+ (_, i) => this.fmt({ weekday: "short" }, new Date(2024, 8, 1 + i))
184
+ // 01/09/2024 foi domingo
185
+ );
186
+ cells = wds.map((w) => `<span class="wd">${w}</span>`).join("") + this.daysHtml(todayK, sel, loc);
187
+ } else if (this.view === "months") {
188
+ cells = [...Array(12)].map((_, i) => {
189
+ const dis = this.monthDisabled(this.cursor.y, i + 1);
190
+ return `<button type="button" class="cell" data-month="${i}" ${dis ? "disabled" : ""}>${this.fmt({ month: "short" }, new Date(this.cursor.y, i, 1))}</button>`;
191
+ }).join("");
192
+ } else {
193
+ const base = Math.floor(this.cursor.y / 12) * 12;
194
+ cells = [...Array(12)].map((_, i) => {
195
+ const y = base + i;
196
+ const dis = this.yearDisabled(y);
197
+ return `<button type="button" class="cell" data-year="${y}" ${dis ? "disabled" : ""}>${y}</button>`;
198
+ }).join("");
199
+ }
200
+ const titleAction = this.view === "days" ? `data-goto="months"` : this.view === "months" ? `data-goto="years"` : "";
201
+ this.setTemplate(`
202
+ <div class="head">
203
+ <button type="button" class="nav" data-nav="-1" aria-label="Anterior">‹</button>
204
+ <button type="button" class="title" part="title" ${titleAction}>${titles[this.view]}</button>
205
+ <button type="button" class="nav" data-nav="1" aria-label="Próximo">›</button>
206
+ </div>
207
+ <div class="grid ${this.view}">${cells}</div>
208
+ `);
209
+ this.root.querySelectorAll("[data-nav]").forEach(
210
+ (b) => b.addEventListener("click", () => this.navigate(Number(b.dataset.nav)))
211
+ );
212
+ const gotoBtn = this.root.querySelector("[data-goto]");
213
+ gotoBtn?.addEventListener("click", () => {
214
+ this.view = gotoBtn.dataset.goto;
215
+ this.render();
216
+ });
217
+ this.root.querySelectorAll("[data-day]").forEach(
218
+ (b) => b.addEventListener("click", () => this.pickDay(Number(b.dataset.day)))
219
+ );
220
+ this.root.querySelectorAll("[data-month]").forEach(
221
+ (b) => b.addEventListener("click", () => {
222
+ this.cursor.m = Number(b.dataset.month);
223
+ this.view = "days";
224
+ this.render();
225
+ })
226
+ );
227
+ this.root.querySelectorAll("[data-year]").forEach(
228
+ (b) => b.addEventListener("click", () => {
229
+ this.cursor.y = Number(b.dataset.year);
230
+ this.view = "months";
231
+ this.render();
232
+ })
233
+ );
234
+ }
235
+ /** Grade de dias com preenchimento do mês anterior. */
236
+ daysHtml(todayK, sel, _loc) {
237
+ const { y, m } = this.cursor;
238
+ const first = new Date(y, m, 1).getDay();
239
+ const total = new Date(y, m + 1, 0).getDate();
240
+ const prevTotal = new Date(y, m, 0).getDate();
241
+ let html = "";
242
+ for (let i = first - 1; i >= 0; i--) {
243
+ html += `<span class="cell muted">${prevTotal - i}</span>`;
244
+ }
245
+ for (let d = 1; d <= total; d++) {
246
+ const k = key(y, m + 1, d);
247
+ const isSel = sel.single === k || sel.start === k || sel.end === k || sel.multi.has(k);
248
+ const inRange = sel.start !== null && sel.end !== null && k > sel.start && k < sel.end;
249
+ const cls = ["cell", isSel ? "sel" : "", inRange ? "in-range" : "", k === todayK ? "today" : ""].filter(Boolean).join(" ");
250
+ html += `<button type="button" class="${cls}" data-day="${k}" ${this.dayDisabled(y, m, d) ? "disabled" : ""}>${d}</button>`;
251
+ }
252
+ return html;
253
+ }
254
+ };
255
+ _FxCalendar.styles = css`
256
+ :host {
257
+ display: inline-block;
258
+ font-family: var(--fx-font-family);
259
+ font-size: var(--fx-font-size);
260
+ color: var(--fx-text-default);
261
+ background: var(--fx-surface-background);
262
+ border: 1px solid var(--fx-border-default);
263
+ border-radius: var(--fx-radius-md);
264
+ box-shadow: var(--fx-shadow-sm);
265
+ padding: var(--fx-space-sm);
266
+ user-select: none;
267
+ }
268
+ :host([disabled]) { opacity: 0.55; pointer-events: none; }
269
+ .head {
270
+ display: flex;
271
+ align-items: center;
272
+ justify-content: space-between;
273
+ gap: var(--fx-space-xs);
274
+ margin-bottom: var(--fx-space-xs);
275
+ }
276
+ .nav,
277
+ .title {
278
+ border: none;
279
+ background: none;
280
+ color: var(--fx-text-default);
281
+ cursor: pointer;
282
+ font: inherit;
283
+ border-radius: var(--fx-radius-sm);
284
+ padding: var(--fx-space-3xs, 4px) var(--fx-space-xs);
285
+ }
286
+ .nav:hover, .title:hover { background: var(--fx-surface-surface-hover); }
287
+ .title { font-weight: var(--fx-font-weight); text-transform: capitalize; flex: 1; }
288
+ .grid {
289
+ display: grid;
290
+ grid-template-columns: repeat(7, 34px);
291
+ gap: 2px;
292
+ }
293
+ .grid.months, .grid.years { grid-template-columns: repeat(4, minmax(52px, 1fr)); }
294
+ .wd {
295
+ text-align: center;
296
+ color: var(--fx-text-muted);
297
+ font-size: calc(var(--fx-font-size) - 2px);
298
+ padding: var(--fx-space-3xs, 4px) 0;
299
+ text-transform: capitalize;
300
+ }
301
+ .cell {
302
+ position: relative;
303
+ border: none;
304
+ background: none;
305
+ font: inherit;
306
+ color: var(--fx-text-default);
307
+ height: 32px;
308
+ border-radius: var(--fx-radius-sm);
309
+ cursor: pointer;
310
+ display: inline-flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ }
314
+ .cell:hover { background: color-mix(in srgb, var(--fx-color-primary) 12%, transparent); }
315
+ .cell.muted { color: var(--fx-text-disabled); }
316
+ .cell.today::after {
317
+ content: '';
318
+ position: absolute;
319
+ bottom: 3px;
320
+ width: 4px;
321
+ height: 4px;
322
+ border-radius: var(--fx-radius-full);
323
+ background: var(--fx-color-primary);
324
+ }
325
+ .cell.sel {
326
+ background: var(--fx-color-primary);
327
+ color: #fff;
328
+ font-weight: var(--fx-font-weight);
329
+ }
330
+ .cell.sel::after { background: #fff; }
331
+ .cell.in-range {
332
+ background: color-mix(in srgb, var(--fx-color-primary) 16%, transparent);
333
+ border-radius: 0;
334
+ }
335
+ .grid.months .cell, .grid.years .cell { height: 40px; }
336
+ .cell[disabled] { opacity: 0.35; cursor: not-allowed; pointer-events: none; }
337
+ `;
338
+ let FxCalendar = _FxCalendar;
339
+ function defineFxCalendar() {
340
+ return defineElement("fx-calendar", FxCalendar);
341
+ }
342
+ export {
343
+ FxCalendar,
344
+ defineFxCalendar
345
+ };
346
+ //# sourceMappingURL=calendar.js.map