sibujs 1.5.0 → 2.1.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 (208) hide show
  1. package/dist/browser.cjs +332 -121
  2. package/dist/browser.d.cts +5 -0
  3. package/dist/browser.d.ts +5 -0
  4. package/dist/browser.js +6 -6
  5. package/dist/build.cjs +1049 -344
  6. package/dist/build.js +15 -13
  7. package/dist/cdn.global.js +17 -16
  8. package/dist/chunk-2RA7SHDA.js +65 -0
  9. package/dist/chunk-2UPRY23K.js +80 -0
  10. package/dist/{chunk-BMPL52BF.js → chunk-3DZP6OIT.js} +118 -66
  11. package/dist/chunk-3JHCYHWN.js +125 -0
  12. package/dist/{chunk-CZUGLNJS.js → chunk-45YP72ZQ.js} +3 -3
  13. package/dist/{chunk-JCDUJN2F.js → chunk-AMK2TYNW.js} +490 -153
  14. package/dist/{chunk-NHUC2QWH.js → chunk-CWBVQML6.js} +1 -1
  15. package/dist/{chunk-XHK6BDAJ.js → chunk-DRUZZAK4.js} +25 -8
  16. package/dist/{chunk-RJ46C3CS.js → chunk-GWWURC5M.js} +71 -20
  17. package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
  18. package/dist/{chunk-2BYQDGN3.js → chunk-KGYT6UO6.js} +234 -63
  19. package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
  20. package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
  21. package/dist/{chunk-XUEEGU5O.js → chunk-NASX6ST2.js} +16 -4
  22. package/dist/{chunk-VQDZK23A.js → chunk-O6EFQ3KT.js} +181 -66
  23. package/dist/{chunk-BGN5ZMP4.js → chunk-OJ3P4ECI.js} +14 -2
  24. package/dist/chunk-ON5MMR2J.js +1327 -0
  25. package/dist/{chunk-SFKNRVCU.js → chunk-P2HSJDDN.js} +135 -79
  26. package/dist/chunk-QO3WC6FS.js +384 -0
  27. package/dist/{chunk-WZSPOOER.js → chunk-RDTDJCAB.js} +8 -5
  28. package/dist/{chunk-7GRNSCFT.js → chunk-TH2ILCYW.js} +312 -185
  29. package/dist/chunk-UCS6AMJ7.js +79 -0
  30. package/dist/{chunk-VAPYJN4X.js → chunk-V6C4FADE.js} +93 -23
  31. package/dist/{chunk-OUZZEE4S.js → chunk-WANSMF2L.js} +17 -11
  32. package/dist/{chunk-23VV7YD3.js → chunk-WIPZPFBQ.js} +25 -30
  33. package/dist/chunk-WZA53FXU.js +149 -0
  34. package/dist/{chunk-BGTHZHJ5.js → chunk-ZAQSMOED.js} +188 -44
  35. package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
  36. package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
  37. package/dist/data.cjs +536 -151
  38. package/dist/data.d.cts +20 -2
  39. package/dist/data.d.ts +20 -2
  40. package/dist/data.js +11 -9
  41. package/dist/devtools.cjs +613 -266
  42. package/dist/devtools.d.cts +1 -1
  43. package/dist/devtools.d.ts +1 -1
  44. package/dist/devtools.js +12 -6
  45. package/dist/ecosystem.cjs +602 -197
  46. package/dist/ecosystem.d.cts +9 -7
  47. package/dist/ecosystem.d.ts +9 -7
  48. package/dist/ecosystem.js +12 -11
  49. package/dist/extras.cjs +3500 -1608
  50. package/dist/extras.d.cts +9 -9
  51. package/dist/extras.d.ts +9 -9
  52. package/dist/extras.js +58 -45
  53. package/dist/index.cjs +1055 -344
  54. package/dist/index.d.cts +85 -8
  55. package/dist/index.d.ts +85 -8
  56. package/dist/index.js +32 -16
  57. package/dist/{introspect-BumjnBKr.d.cts → introspect-2TOlQ7oa.d.cts} +25 -3
  58. package/dist/{introspect-CZrlcaYy.d.ts → introspect-DnIpHQQz.d.ts} +25 -3
  59. package/dist/motion.cjs +122 -63
  60. package/dist/motion.js +4 -4
  61. package/dist/patterns.cjs +450 -110
  62. package/dist/patterns.d.cts +11 -12
  63. package/dist/patterns.d.ts +11 -12
  64. package/dist/patterns.js +7 -7
  65. package/dist/performance.cjs +373 -149
  66. package/dist/performance.d.cts +23 -16
  67. package/dist/performance.d.ts +23 -16
  68. package/dist/performance.js +13 -8
  69. package/dist/plugin-D30wlGW5.d.cts +71 -0
  70. package/dist/plugin-D30wlGW5.d.ts +71 -0
  71. package/dist/plugins.cjs +729 -301
  72. package/dist/plugins.d.cts +10 -3
  73. package/dist/plugins.d.ts +10 -3
  74. package/dist/plugins.js +106 -38
  75. package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
  76. package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
  77. package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
  78. package/dist/ssr.cjs +736 -274
  79. package/dist/ssr.d.cts +26 -6
  80. package/dist/ssr.d.ts +26 -6
  81. package/dist/ssr.js +12 -11
  82. package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
  83. package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
  84. package/dist/testing.cjs +303 -76
  85. package/dist/testing.d.cts +17 -4
  86. package/dist/testing.d.ts +17 -4
  87. package/dist/testing.js +100 -44
  88. package/dist/ui.cjs +589 -178
  89. package/dist/ui.d.cts +1 -1
  90. package/dist/ui.d.ts +1 -1
  91. package/dist/ui.js +20 -17
  92. package/dist/widgets.cjs +1103 -146
  93. package/dist/widgets.d.cts +104 -2
  94. package/dist/widgets.d.ts +104 -2
  95. package/dist/widgets.js +9 -7
  96. package/package.json +8 -2
  97. package/dist/chunk-32DY64NT.js +0 -282
  98. package/dist/chunk-3AIRKM3B.js +0 -1263
  99. package/dist/chunk-3ARAQO7B.js +0 -398
  100. package/dist/chunk-3CRQALYP.js +0 -877
  101. package/dist/chunk-4EI4AG32.js +0 -482
  102. package/dist/chunk-4MYMUBRS.js +0 -21
  103. package/dist/chunk-5ZYQ6KDD.js +0 -154
  104. package/dist/chunk-6BMPXPUW.js +0 -26
  105. package/dist/chunk-6HLLIF3K.js +0 -398
  106. package/dist/chunk-6LSNVCS2.js +0 -937
  107. package/dist/chunk-6SA3QQES.js +0 -61
  108. package/dist/chunk-77L6NL3X.js +0 -1097
  109. package/dist/chunk-7BF6TK55.js +0 -1097
  110. package/dist/chunk-7TQKR4PP.js +0 -294
  111. package/dist/chunk-7V26P53V.js +0 -712
  112. package/dist/chunk-AZ3ISID5.js +0 -298
  113. package/dist/chunk-B7SWRFUT.js +0 -332
  114. package/dist/chunk-BTU3TJDS.js +0 -365
  115. package/dist/chunk-BW3WT46K.js +0 -937
  116. package/dist/chunk-C6KFWOFV.js +0 -616
  117. package/dist/chunk-CHF5OHIA.js +0 -61
  118. package/dist/chunk-CHJ27IGK.js +0 -26
  119. package/dist/chunk-CMBFNA7L.js +0 -27
  120. package/dist/chunk-DAHRH4ON.js +0 -331
  121. package/dist/chunk-DKOHBI74.js +0 -924
  122. package/dist/chunk-DTCOOBMX.js +0 -725
  123. package/dist/chunk-EBGIRKQY.js +0 -616
  124. package/dist/chunk-EUZND3CB.js +0 -27
  125. package/dist/chunk-EVCZO745.js +0 -365
  126. package/dist/chunk-EWFVA3TJ.js +0 -282
  127. package/dist/chunk-F3FA4F32.js +0 -292
  128. package/dist/chunk-FGOEVHY3.js +0 -60
  129. package/dist/chunk-G3BOQPVO.js +0 -365
  130. package/dist/chunk-GCOK2LC3.js +0 -282
  131. package/dist/chunk-GJPXRJ45.js +0 -37
  132. package/dist/chunk-HGMJFBC7.js +0 -654
  133. package/dist/chunk-JAKHTMQU.js +0 -1000
  134. package/dist/chunk-JCI5M6U6.js +0 -956
  135. package/dist/chunk-K4G4ZQNR.js +0 -286
  136. package/dist/chunk-K5ZUMYVS.js +0 -89
  137. package/dist/chunk-KQPDEVVS.js +0 -398
  138. package/dist/chunk-L6JRBDNS.js +0 -60
  139. package/dist/chunk-LA6KQEDU.js +0 -712
  140. package/dist/chunk-MB6QFH3I.js +0 -2776
  141. package/dist/chunk-MDVXJWFN.js +0 -304
  142. package/dist/chunk-MEZVEBPN.js +0 -2008
  143. package/dist/chunk-MK4ERFYL.js +0 -2249
  144. package/dist/chunk-MLKGABMK.js +0 -9
  145. package/dist/chunk-MQ5GOYPH.js +0 -2249
  146. package/dist/chunk-MYRV7VDM.js +0 -742
  147. package/dist/chunk-N6IZB6KJ.js +0 -567
  148. package/dist/chunk-NEKUBFPT.js +0 -60
  149. package/dist/chunk-NMRUZALC.js +0 -1097
  150. package/dist/chunk-NYVAC6P5.js +0 -37
  151. package/dist/chunk-NZIIMDWI.js +0 -84
  152. package/dist/chunk-OF7UZIVB.js +0 -725
  153. package/dist/chunk-P3XWXJZU.js +0 -282
  154. package/dist/chunk-P6W3STU4.js +0 -2249
  155. package/dist/chunk-PBHF5WKN.js +0 -616
  156. package/dist/chunk-PDZQY43A.js +0 -616
  157. package/dist/chunk-PTQJDMRT.js +0 -146
  158. package/dist/chunk-PZEGYCF5.js +0 -61
  159. package/dist/chunk-QBMDLBU2.js +0 -975
  160. package/dist/chunk-QWZG56ET.js +0 -2744
  161. package/dist/chunk-RQGQSLQK.js +0 -725
  162. package/dist/chunk-SDLZDHKP.js +0 -107
  163. package/dist/chunk-TDGZL5CU.js +0 -365
  164. package/dist/chunk-TNQWPPE6.js +0 -37
  165. package/dist/chunk-TSOKIX5Z.js +0 -654
  166. package/dist/chunk-UHNL42EF.js +0 -2730
  167. package/dist/chunk-UNXCEF6S.js +0 -21
  168. package/dist/chunk-V2XTI523.js +0 -347
  169. package/dist/chunk-VAU366PN.js +0 -2241
  170. package/dist/chunk-VMVDTCXB.js +0 -712
  171. package/dist/chunk-VQNQZCWJ.js +0 -61
  172. package/dist/chunk-VRW3FULF.js +0 -725
  173. package/dist/chunk-WADYRCO2.js +0 -304
  174. package/dist/chunk-WILQZRO4.js +0 -282
  175. package/dist/chunk-WR5D4EGH.js +0 -26
  176. package/dist/chunk-WUHJISPP.js +0 -298
  177. package/dist/chunk-XYU6TZOW.js +0 -182
  178. package/dist/chunk-Y6GP4QGG.js +0 -276
  179. package/dist/chunk-YECR7UIA.js +0 -347
  180. package/dist/chunk-YUTWTI4B.js +0 -654
  181. package/dist/chunk-Z65KYU7I.js +0 -26
  182. package/dist/chunk-Z6POF5YC.js +0 -975
  183. package/dist/chunk-ZBJP6WFL.js +0 -482
  184. package/dist/chunk-ZD6OAMTH.js +0 -277
  185. package/dist/chunk-ZWKZCBO6.js +0 -317
  186. package/dist/contracts-DDrwxvJ-.d.cts +0 -245
  187. package/dist/contracts-DDrwxvJ-.d.ts +0 -245
  188. package/dist/contracts-DOrhwbke.d.cts +0 -245
  189. package/dist/contracts-DOrhwbke.d.ts +0 -245
  190. package/dist/contracts-xo5ckdRP.d.cts +0 -240
  191. package/dist/contracts-xo5ckdRP.d.ts +0 -240
  192. package/dist/customElement-BKQfbSZQ.d.cts +0 -262
  193. package/dist/customElement-BKQfbSZQ.d.ts +0 -262
  194. package/dist/customElement-D2DJp_xn.d.cts +0 -313
  195. package/dist/customElement-D2DJp_xn.d.ts +0 -313
  196. package/dist/customElement-yz8uyk-0.d.cts +0 -308
  197. package/dist/customElement-yz8uyk-0.d.ts +0 -308
  198. package/dist/introspect-Cb0zgpi2.d.cts +0 -477
  199. package/dist/introspect-Y2xNXGSf.d.ts +0 -477
  200. package/dist/plugin-Bek4RhJY.d.cts +0 -43
  201. package/dist/plugin-Bek4RhJY.d.ts +0 -43
  202. package/dist/ssr-3RXHP5ES.js +0 -38
  203. package/dist/ssr-6GIMY5MX.js +0 -38
  204. package/dist/ssr-BA6sxxUd.d.cts +0 -135
  205. package/dist/ssr-BA6sxxUd.d.ts +0 -135
  206. package/dist/ssr-WKUPVSSK.js +0 -36
  207. package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
  208. package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
@@ -1,956 +0,0 @@
1
- import {
2
- bindAttribute
3
- } from "./chunk-PTQJDMRT.js";
4
- import {
5
- derived
6
- } from "./chunk-NEKUBFPT.js";
7
- import {
8
- effect
9
- } from "./chunk-CHF5OHIA.js";
10
- import {
11
- signal
12
- } from "./chunk-WZSPOOER.js";
13
- import {
14
- track
15
- } from "./chunk-ZD6OAMTH.js";
16
-
17
- // src/ui/form.ts
18
- function required(message = "This field is required") {
19
- return (value) => {
20
- if (value == null || value === "" || Array.isArray(value) && value.length === 0) {
21
- return message;
22
- }
23
- return null;
24
- };
25
- }
26
- function minLength(min2, message) {
27
- return (value) => {
28
- if (value && value.length < min2) {
29
- return message || `Must be at least ${min2} characters`;
30
- }
31
- return null;
32
- };
33
- }
34
- function maxLength(max2, message) {
35
- return (value) => {
36
- if (value && value.length > max2) {
37
- return message || `Must be at most ${max2} characters`;
38
- }
39
- return null;
40
- };
41
- }
42
- function matchesPattern(regex, message = "Invalid format") {
43
- return (value) => {
44
- if (value && !regex.test(value)) {
45
- return message;
46
- }
47
- return null;
48
- };
49
- }
50
- function email(message = "Invalid email address") {
51
- return matchesPattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, message);
52
- }
53
- function min(minVal, message) {
54
- return (value) => {
55
- if (value != null && value < minVal) {
56
- return message || `Must be at least ${minVal}`;
57
- }
58
- return null;
59
- };
60
- }
61
- function max(maxVal, message) {
62
- return (value) => {
63
- if (value != null && value > maxVal) {
64
- return message || `Must be at most ${maxVal}`;
65
- }
66
- return null;
67
- };
68
- }
69
- function custom(fn, message) {
70
- return (value) => fn(value) ? null : message;
71
- }
72
- function bindField(field, extras) {
73
- const fieldOn = {
74
- input: (e) => {
75
- const target = e.target;
76
- if (target.type === "checkbox") {
77
- field.set(target.checked);
78
- } else {
79
- field.set(target.value);
80
- }
81
- },
82
- change: (e) => {
83
- const target = e.target;
84
- if ("checked" in target && target.type === "checkbox") {
85
- field.set(target.checked);
86
- } else {
87
- field.set(target.value);
88
- }
89
- },
90
- blur: () => field.touch()
91
- };
92
- const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
93
- const mergedOn = extraOn && typeof extraOn === "object" ? { ...fieldOn, ...extraOn } : fieldOn;
94
- return {
95
- value: field.value,
96
- on: mergedOn,
97
- ...restExtras
98
- };
99
- }
100
- function form(config) {
101
- const fieldEntries = Object.entries(config);
102
- const fieldMap = {};
103
- const [manualErrors, setManualErrors] = signal({});
104
- for (const [name, cfg] of fieldEntries) {
105
- const [value, setValue] = signal(cfg.initial);
106
- const [isTouched, setTouched] = signal(false);
107
- const error = derived(() => {
108
- const manual = manualErrors();
109
- if (manual[name]) return manual[name];
110
- const val = value();
111
- if (!cfg.validators) return null;
112
- for (const validator of cfg.validators) {
113
- const msg = validator(val);
114
- if (msg) return msg;
115
- }
116
- return null;
117
- });
118
- fieldMap[name] = {
119
- value,
120
- set: setValue,
121
- error,
122
- touched: isTouched,
123
- touch: () => setTouched(true),
124
- reset: () => {
125
- setValue(cfg.initial);
126
- setTouched(false);
127
- setManualErrors((prev) => ({ ...prev, [name]: null }));
128
- }
129
- };
130
- }
131
- const errors = derived(() => {
132
- const result = {};
133
- for (const [name, field] of Object.entries(fieldMap)) {
134
- result[name] = field.error();
135
- }
136
- return result;
137
- });
138
- const isValid = derived(() => {
139
- for (const field of Object.values(fieldMap)) {
140
- if (field.error() != null) return false;
141
- }
142
- return true;
143
- });
144
- const isDirty = derived(() => {
145
- for (const [name, cfg] of fieldEntries) {
146
- if (!Object.is(fieldMap[name].value(), cfg.initial)) return true;
147
- }
148
- return false;
149
- });
150
- const touchedState = derived(() => {
151
- const result = {};
152
- for (const [name, field] of Object.entries(fieldMap)) {
153
- result[name] = field.touched();
154
- }
155
- return result;
156
- });
157
- const values = derived(() => {
158
- const result = {};
159
- for (const [name, field] of Object.entries(fieldMap)) {
160
- result[name] = field.value();
161
- }
162
- return result;
163
- });
164
- function handleSubmit(onSubmit) {
165
- return (e) => {
166
- if (e) e.preventDefault();
167
- for (const field of Object.values(fieldMap)) {
168
- field.touch();
169
- }
170
- if (isValid()) {
171
- onSubmit(values());
172
- }
173
- };
174
- }
175
- function reset() {
176
- for (const field of Object.values(fieldMap)) {
177
- field.reset();
178
- }
179
- }
180
- function setError(field, message) {
181
- setManualErrors((prev) => ({ ...prev, [field]: message }));
182
- }
183
- return {
184
- fields: fieldMap,
185
- errors,
186
- isValid,
187
- isDirty,
188
- touched: touchedState,
189
- values,
190
- handleSubmit,
191
- reset,
192
- setError
193
- };
194
- }
195
-
196
- // src/ui/virtualList.ts
197
- function VirtualList(props) {
198
- const overscan = props.overscan ?? 3;
199
- const [scrollTop, setScrollTop] = signal(0);
200
- const container = document.createElement("div");
201
- container.style.overflow = "auto";
202
- container.style.height = `${props.containerHeight}px`;
203
- container.style.position = "relative";
204
- if (props.class) container.className = props.class;
205
- const spacer = document.createElement("div");
206
- spacer.style.position = "relative";
207
- const content = document.createElement("div");
208
- content.style.position = "absolute";
209
- content.style.left = "0";
210
- content.style.right = "0";
211
- spacer.appendChild(content);
212
- container.appendChild(spacer);
213
- container.addEventListener("scroll", () => {
214
- setScrollTop(container.scrollTop);
215
- });
216
- const update = () => {
217
- const items = props.items();
218
- const totalHeight = items.length * props.itemHeight;
219
- spacer.style.height = `${totalHeight}px`;
220
- const currentScroll = scrollTop();
221
- const startIndex = Math.max(0, Math.floor(currentScroll / props.itemHeight) - overscan);
222
- const visibleCount = Math.ceil(props.containerHeight / props.itemHeight) + 2 * overscan;
223
- const endIndex = Math.min(items.length, startIndex + visibleCount);
224
- content.style.top = `${startIndex * props.itemHeight}px`;
225
- content.innerHTML = "";
226
- for (let i = startIndex; i < endIndex; i++) {
227
- const itemEl = props.renderItem(items[i], i);
228
- itemEl.style.height = `${props.itemHeight}px`;
229
- itemEl.style.boxSizing = "border-box";
230
- content.appendChild(itemEl);
231
- }
232
- };
233
- effect(update);
234
- return container;
235
- }
236
-
237
- // src/ui/intersection.ts
238
- function intersection(options) {
239
- const [isIntersecting, setIsIntersecting] = signal(false);
240
- const [ratio, setRatio] = signal(0);
241
- let observer = null;
242
- let currentElement = null;
243
- function observe(element) {
244
- unobserve();
245
- currentElement = element;
246
- observer = new IntersectionObserver((entries) => {
247
- const entry = entries[0];
248
- if (entry) {
249
- setIsIntersecting(entry.isIntersecting);
250
- setRatio(entry.intersectionRatio);
251
- }
252
- }, options);
253
- observer.observe(element);
254
- }
255
- function unobserve() {
256
- if (observer) {
257
- if (currentElement) observer.unobserve(currentElement);
258
- observer.disconnect();
259
- observer = null;
260
- currentElement = null;
261
- }
262
- }
263
- return {
264
- isIntersecting,
265
- intersectionRatio: ratio,
266
- observe,
267
- unobserve
268
- };
269
- }
270
- function lazyLoad(element, loader, options) {
271
- const observer = new IntersectionObserver((entries) => {
272
- for (const entry of entries) {
273
- if (entry.isIntersecting) {
274
- loader();
275
- observer.disconnect();
276
- break;
277
- }
278
- }
279
- }, options);
280
- observer.observe(element);
281
- return () => observer.disconnect();
282
- }
283
-
284
- // src/ui/inputMask.ts
285
- function inputMask(options) {
286
- const placeholder = options.placeholder || "_";
287
- const [value, setValue] = signal("");
288
- const [rawValue, setRawValue] = signal("");
289
- function applyMask(raw) {
290
- let result = "";
291
- let rawIndex = 0;
292
- for (let i = 0; i < options.pattern.length && rawIndex < raw.length; i++) {
293
- const maskChar = options.pattern[i];
294
- if (maskChar === "9") {
295
- while (rawIndex < raw.length && !/\d/.test(raw[rawIndex])) rawIndex++;
296
- if (rawIndex < raw.length) {
297
- result += raw[rawIndex++];
298
- }
299
- } else if (maskChar === "A") {
300
- while (rawIndex < raw.length && !/[a-zA-Z]/.test(raw[rawIndex])) rawIndex++;
301
- if (rawIndex < raw.length) {
302
- result += raw[rawIndex++];
303
- }
304
- } else if (maskChar === "*") {
305
- result += raw[rawIndex++];
306
- } else {
307
- result += maskChar;
308
- if (raw[rawIndex] === maskChar) rawIndex++;
309
- }
310
- }
311
- return result;
312
- }
313
- function extractRaw(masked) {
314
- let raw = "";
315
- for (let i = 0; i < masked.length && i < options.pattern.length; i++) {
316
- const maskChar = options.pattern[i];
317
- if (maskChar === "9" || maskChar === "A" || maskChar === "*") {
318
- raw += masked[i];
319
- }
320
- }
321
- return raw;
322
- }
323
- function bind(input) {
324
- input.addEventListener("input", () => {
325
- const raw = input.value.replace(/[^a-zA-Z0-9]/g, "");
326
- const masked = applyMask(raw);
327
- setValue(masked);
328
- setRawValue(extractRaw(masked));
329
- input.value = masked;
330
- });
331
- input.addEventListener("focus", () => {
332
- if (!input.value) {
333
- const display = options.pattern.replace(/9/g, placeholder).replace(/A/g, placeholder).replace(/\*/g, placeholder);
334
- input.placeholder = display;
335
- }
336
- });
337
- }
338
- return { value, rawValue, bind };
339
- }
340
- function phoneMask() {
341
- return { pattern: "(999) 999-9999" };
342
- }
343
- function dateMask() {
344
- return { pattern: "99/99/9999" };
345
- }
346
- function creditCardMask() {
347
- return { pattern: "9999 9999 9999 9999" };
348
- }
349
- function timeMask() {
350
- return { pattern: "99:99" };
351
- }
352
- function ssnMask() {
353
- return { pattern: "999-99-9999" };
354
- }
355
- function zipMask() {
356
- return { pattern: "99999" };
357
- }
358
-
359
- // src/ui/a11y.ts
360
- function aria(element, attrs) {
361
- for (const [key, value] of Object.entries(attrs)) {
362
- const ariaKey = key.startsWith("aria-") ? key : `aria-${key}`;
363
- if (typeof value === "function") {
364
- const getter = value;
365
- track(() => {
366
- element.setAttribute(ariaKey, String(getter()));
367
- });
368
- } else {
369
- element.setAttribute(ariaKey, String(value));
370
- }
371
- }
372
- }
373
- function focus() {
374
- const [isFocused, setIsFocused] = signal(false);
375
- let currentElement = null;
376
- function bind(element) {
377
- currentElement = element;
378
- element.addEventListener("focus", () => setIsFocused(true));
379
- element.addEventListener("blur", () => setIsFocused(false));
380
- }
381
- function focus2() {
382
- currentElement?.focus();
383
- }
384
- function blur() {
385
- currentElement?.blur();
386
- }
387
- return { isFocused, focus: focus2, blur, bind };
388
- }
389
- function FocusTrap(nodes, options = {}) {
390
- const container = document.createElement("div");
391
- container.setAttribute("data-sibu-focus-trap", "true");
392
- container.appendChild(nodes);
393
- const previouslyFocused = document.activeElement;
394
- container.addEventListener("keydown", (e) => {
395
- if (e.key !== "Tab") return;
396
- const focusable = container.querySelectorAll(
397
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
398
- );
399
- if (focusable.length === 0) return;
400
- const first = focusable[0];
401
- const last = focusable[focusable.length - 1];
402
- if (e.shiftKey) {
403
- if (document.activeElement === first) {
404
- e.preventDefault();
405
- last.focus();
406
- }
407
- } else {
408
- if (document.activeElement === last) {
409
- e.preventDefault();
410
- first.focus();
411
- }
412
- }
413
- });
414
- if (options.autoFocus !== false) {
415
- queueMicrotask(() => {
416
- const first = container.querySelector(
417
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
418
- );
419
- first?.focus();
420
- });
421
- }
422
- if (options.restoreFocus !== false) {
423
- const observer = new MutationObserver((mutations) => {
424
- for (const mutation of mutations) {
425
- for (const removed of Array.from(mutation.removedNodes)) {
426
- if (removed === container || removed.contains(container)) {
427
- previouslyFocused?.focus();
428
- observer.disconnect();
429
- return;
430
- }
431
- }
432
- }
433
- });
434
- queueMicrotask(() => {
435
- if (container.parentNode) {
436
- observer.observe(container.parentNode, { childList: true });
437
- }
438
- });
439
- }
440
- return container;
441
- }
442
- function hotkey(combo, handler, options = {}) {
443
- let key = combo;
444
- let needCtrl = options.ctrl ?? false;
445
- let needShift = options.shift ?? false;
446
- let needAlt = options.alt ?? false;
447
- let needMeta = options.meta ?? false;
448
- if (combo.includes("+")) {
449
- const parts = combo.toLowerCase().split("+");
450
- key = parts[parts.length - 1];
451
- for (let i = 0; i < parts.length - 1; i++) {
452
- const mod = parts[i];
453
- if (mod === "ctrl" || mod === "control") needCtrl = true;
454
- else if (mod === "shift") needShift = true;
455
- else if (mod === "alt") needAlt = true;
456
- else if (mod === "meta" || mod === "cmd" || mod === "command") needMeta = true;
457
- }
458
- }
459
- const listener = (e) => {
460
- const ke = e;
461
- if (ke.key.toLowerCase() !== key.toLowerCase()) return;
462
- if (needCtrl !== ke.ctrlKey) return;
463
- if (needShift !== ke.shiftKey) return;
464
- if (needAlt !== ke.altKey) return;
465
- if (needMeta !== ke.metaKey) return;
466
- if (options.preventDefault) ke.preventDefault();
467
- handler(ke);
468
- };
469
- document.addEventListener("keydown", listener);
470
- return () => document.removeEventListener("keydown", listener);
471
- }
472
- function announce(message, priority = "polite") {
473
- let region = document.getElementById(`sibu-announce-${priority}`);
474
- if (!region) {
475
- region = document.createElement("div");
476
- region.id = `sibu-announce-${priority}`;
477
- region.setAttribute("aria-live", priority);
478
- region.setAttribute("aria-atomic", "true");
479
- region.setAttribute("role", priority === "assertive" ? "alert" : "status");
480
- region.style.cssText = "position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;";
481
- document.body.appendChild(region);
482
- }
483
- region.textContent = "";
484
- requestAnimationFrame(() => {
485
- if (region) region.textContent = message;
486
- });
487
- }
488
-
489
- // src/ui/scopedStyle.ts
490
- var scopeCounter = 0;
491
- function decodeCssEscapes(css) {
492
- return css.replace(/\\([0-9a-f]{1,6})[ \t\n\r\f]?|\\([^\n])/gi, (_match, hex, ch) => {
493
- if (hex) {
494
- const code = Number.parseInt(hex, 16);
495
- if (Number.isFinite(code) && code > 0 && code <= 1114111) {
496
- try {
497
- return String.fromCodePoint(code);
498
- } catch {
499
- return "";
500
- }
501
- }
502
- return "";
503
- }
504
- return ch || "";
505
- });
506
- }
507
- function sanitizeCSS(css) {
508
- let sanitized = decodeCssEscapes(css);
509
- sanitized = sanitized.replace(/@import\s+[^;]+;/gi, "/* @import removed */");
510
- sanitized = sanitized.replace(/url\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* url() removed */");
511
- sanitized = sanitized.replace(/expression\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* expression() removed */");
512
- sanitized = sanitized.replace(/-moz-binding\s*:[^;]+;/gi, "/* -moz-binding removed */");
513
- sanitized = sanitized.replace(/behavior\s*:[^;]+;/gi, "/* behavior removed */");
514
- return sanitized;
515
- }
516
- function scopedStyle(css) {
517
- const id = `sibu-s${scopeCounter++}`;
518
- const attr = `data-${id}`;
519
- const safeCss = sanitizeCSS(css);
520
- const scopedCSS = safeCss.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, delimiter) => {
521
- const trimmed = selector.trim();
522
- if (trimmed.startsWith("@") || trimmed.startsWith("from") || trimmed.startsWith("to") || /^\d+%$/.test(trimmed)) {
523
- return match;
524
- }
525
- return `${trimmed}[${attr}]${delimiter}`;
526
- });
527
- if (typeof document !== "undefined") {
528
- const styleEl = document.createElement("style");
529
- styleEl.setAttribute("data-sibu-scope", id);
530
- styleEl.textContent = scopedCSS;
531
- document.head.appendChild(styleEl);
532
- }
533
- return { scope: id, attr };
534
- }
535
- function withScopedStyle(css, component) {
536
- let style = null;
537
- return (props) => {
538
- if (!style) {
539
- style = scopedStyle(css);
540
- }
541
- const el = component(props);
542
- applyScopeRecursive(el, style.attr);
543
- return el;
544
- };
545
- }
546
- function applyScopeRecursive(element, attr) {
547
- element.setAttribute(attr, "");
548
- for (const child of Array.from(element.children)) {
549
- if (child instanceof HTMLElement) {
550
- applyScopeRecursive(child, attr);
551
- }
552
- }
553
- }
554
- function removeScopedStyle(scopeId) {
555
- const el = document.head.querySelector(`style[data-sibu-scope="${scopeId}"]`);
556
- if (el) el.remove();
557
- }
558
-
559
- // src/ui/reactiveAttr.ts
560
- function bindAttrs(el, attrs) {
561
- const teardowns = [];
562
- for (const [attr, value] of Object.entries(attrs)) {
563
- if (typeof value === "function") {
564
- const teardown = bindAttribute(el, attr, value);
565
- teardowns.push(teardown);
566
- } else if (typeof value === "boolean") {
567
- if (value) {
568
- el.setAttribute(attr, "");
569
- } else {
570
- el.removeAttribute(attr);
571
- }
572
- } else {
573
- el.setAttribute(attr, String(value));
574
- }
575
- }
576
- return () => {
577
- for (const td of teardowns) {
578
- td();
579
- }
580
- };
581
- }
582
- function bindBoolAttr(el, attr, getter) {
583
- if (typeof getter !== "function") {
584
- if (getter) {
585
- el.setAttribute(attr, "");
586
- } else {
587
- el.removeAttribute(attr);
588
- }
589
- return () => {
590
- };
591
- }
592
- const reactiveGetter = getter;
593
- function commit() {
594
- let value;
595
- try {
596
- value = reactiveGetter();
597
- } catch {
598
- return;
599
- }
600
- if (value) {
601
- el.setAttribute(attr, "");
602
- } else {
603
- el.removeAttribute(attr);
604
- }
605
- }
606
- const teardown = track(commit);
607
- return teardown;
608
- }
609
- function bindData(el, key, getter) {
610
- const dataAttr = `data-${key}`;
611
- if (typeof getter !== "function") {
612
- el.setAttribute(dataAttr, String(getter));
613
- return () => {
614
- };
615
- }
616
- return bindAttribute(el, dataAttr, getter);
617
- }
618
-
619
- // src/ui/dialog.ts
620
- function dialog() {
621
- const [isOpen, setIsOpen] = signal(false);
622
- let listenerAttached = false;
623
- function handleKeydown(event) {
624
- if (event.key === "Escape") {
625
- close();
626
- }
627
- }
628
- function open() {
629
- setIsOpen(true);
630
- if (typeof window !== "undefined" && !listenerAttached) {
631
- window.addEventListener("keydown", handleKeydown);
632
- listenerAttached = true;
633
- }
634
- }
635
- function close() {
636
- setIsOpen(false);
637
- if (typeof window !== "undefined" && listenerAttached) {
638
- window.removeEventListener("keydown", handleKeydown);
639
- listenerAttached = false;
640
- }
641
- }
642
- function toggle() {
643
- if (isOpen()) {
644
- close();
645
- } else {
646
- open();
647
- }
648
- }
649
- return { open, close, isOpen, toggle };
650
- }
651
-
652
- // src/ui/toast.ts
653
- var toastCounter = 0;
654
- function toast(options) {
655
- const duration = options?.duration ?? 3e3;
656
- const maxToasts = options?.maxToasts ?? Infinity;
657
- const [toasts, setToasts] = signal([]);
658
- const timers = /* @__PURE__ */ new Map();
659
- function show(message, type) {
660
- const id = `toast-${++toastCounter}`;
661
- const toast2 = { id, message, type };
662
- setToasts((prev) => {
663
- const next = [...prev, toast2];
664
- if (next.length > maxToasts) {
665
- const removed = next.splice(0, next.length - maxToasts);
666
- for (const r of removed) {
667
- clearTimerForToast(r.id);
668
- }
669
- }
670
- return next;
671
- });
672
- if (duration > 0) {
673
- const timer = setTimeout(() => {
674
- dismiss(id);
675
- }, duration);
676
- timers.set(id, timer);
677
- }
678
- return id;
679
- }
680
- function dismiss(id) {
681
- clearTimerForToast(id);
682
- setToasts((prev) => prev.filter((t) => t.id !== id));
683
- }
684
- function dismissAll() {
685
- for (const timer of timers.values()) {
686
- clearTimeout(timer);
687
- }
688
- timers.clear();
689
- setToasts([]);
690
- }
691
- function clearTimerForToast(id) {
692
- const timer = timers.get(id);
693
- if (timer !== void 0) {
694
- clearTimeout(timer);
695
- timers.delete(id);
696
- }
697
- }
698
- return {
699
- toasts,
700
- show,
701
- info: (message) => show(message, "info"),
702
- success: (message) => show(message, "success"),
703
- error: (message) => show(message, "error"),
704
- warning: (message) => show(message, "warning"),
705
- dismiss,
706
- dismissAll
707
- };
708
- }
709
-
710
- // src/ui/infiniteScroll.ts
711
- function infiniteScroll(options) {
712
- const { onLoadMore, hasMore, threshold = 0 } = options;
713
- const [loading, setLoading] = signal(false);
714
- const sentinelRef = { current: null };
715
- let observer = null;
716
- let disposed = false;
717
- function createObserver() {
718
- if (typeof IntersectionObserver === "undefined") return;
719
- observer = new IntersectionObserver(
720
- (entries) => {
721
- const entry = entries[0];
722
- if (entry?.isIntersecting && !loading() && hasMore() && !disposed) {
723
- loadMore();
724
- }
725
- },
726
- { threshold }
727
- );
728
- if (sentinelRef.current) {
729
- observer.observe(sentinelRef.current);
730
- }
731
- }
732
- async function loadMore() {
733
- setLoading(true);
734
- try {
735
- await onLoadMore();
736
- } finally {
737
- setLoading(false);
738
- }
739
- }
740
- const originalRef = sentinelRef;
741
- let _current = null;
742
- Object.defineProperty(originalRef, "current", {
743
- get() {
744
- return _current;
745
- },
746
- set(el) {
747
- _current = el;
748
- if (observer) {
749
- observer.disconnect();
750
- observer = null;
751
- }
752
- if (el && !disposed) {
753
- createObserver();
754
- }
755
- },
756
- configurable: true
757
- });
758
- function dispose() {
759
- disposed = true;
760
- if (observer) {
761
- observer.disconnect();
762
- observer = null;
763
- }
764
- }
765
- return { sentinelRef: originalRef, loading, dispose };
766
- }
767
-
768
- // src/ui/pagination.ts
769
- function pagination(options) {
770
- const pageSizeValue = options.pageSize ?? 10;
771
- const [page, setPage] = signal(options.initialPage ?? 1);
772
- const [pageSize] = signal(pageSizeValue);
773
- const totalPages = derived(() => {
774
- const total = options.totalItems();
775
- return Math.max(1, Math.ceil(total / pageSizeValue));
776
- });
777
- const startIndex = derived(() => {
778
- return (page() - 1) * pageSizeValue;
779
- });
780
- const endIndex = derived(() => {
781
- const end = page() * pageSizeValue;
782
- const total = options.totalItems();
783
- return Math.min(end, total);
784
- });
785
- function next() {
786
- if (page() < totalPages()) {
787
- setPage((p) => p + 1);
788
- }
789
- }
790
- function prev() {
791
- if (page() > 1) {
792
- setPage((p) => p - 1);
793
- }
794
- }
795
- function goTo(target) {
796
- const clamped = Math.max(1, Math.min(target, totalPages()));
797
- setPage(clamped);
798
- }
799
- return { page, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
800
- }
801
-
802
- // src/ui/eventBus.ts
803
- function eventBus() {
804
- const listeners = /* @__PURE__ */ new Map();
805
- function on(event, handler) {
806
- let set = listeners.get(event);
807
- if (!set) {
808
- set = /* @__PURE__ */ new Set();
809
- listeners.set(event, set);
810
- }
811
- set.add(handler);
812
- return () => off(event, handler);
813
- }
814
- function emit(event, data) {
815
- const set = listeners.get(event);
816
- if (set) {
817
- for (const handler of set) {
818
- handler(data);
819
- }
820
- }
821
- }
822
- function off(event, handler) {
823
- const set = listeners.get(event);
824
- if (set) {
825
- set.delete(handler);
826
- if (set.size === 0) {
827
- listeners.delete(event);
828
- }
829
- }
830
- }
831
- function clear() {
832
- listeners.clear();
833
- }
834
- return { on, emit, off, clear };
835
- }
836
-
837
- // src/platform/customElement.ts
838
- function defineElement(name, component, options = {}) {
839
- if (customElements.get(name)) return;
840
- const observed = options.observedAttributes || [];
841
- class SibuElement extends HTMLElement {
842
- constructor() {
843
- super();
844
- this._rendered = false;
845
- if (options.shadow !== false) {
846
- this._root = this.attachShadow({ mode: options.mode || "open" });
847
- } else {
848
- this._root = this;
849
- }
850
- }
851
- static get observedAttributes() {
852
- return observed;
853
- }
854
- connectedCallback() {
855
- this._render();
856
- }
857
- disconnectedCallback() {
858
- if (this._root instanceof ShadowRoot) {
859
- this._root.innerHTML = "";
860
- }
861
- this._rendered = false;
862
- }
863
- attributeChangedCallback() {
864
- if (this._rendered) {
865
- this._render();
866
- }
867
- }
868
- _render() {
869
- const props = this._getProps();
870
- if (this._root instanceof ShadowRoot) {
871
- this._root.innerHTML = "";
872
- } else {
873
- while (this._root.firstChild) {
874
- this._root.removeChild(this._root.firstChild);
875
- }
876
- }
877
- if (options.styles && this._root instanceof ShadowRoot) {
878
- const styleEl = document.createElement("style");
879
- styleEl.textContent = options.styles;
880
- this._root.appendChild(styleEl);
881
- }
882
- const el = component(props, this);
883
- this._root.appendChild(el);
884
- this._rendered = true;
885
- }
886
- _getProps() {
887
- const props = {};
888
- for (const attr of this.attributes) {
889
- props[attr.name] = attr.value;
890
- }
891
- return props;
892
- }
893
- }
894
- customElements.define(name, SibuElement);
895
- }
896
- function svgElement(tag, props = {}, ...nodes) {
897
- const SVG_NS = "http://www.w3.org/2000/svg";
898
- const el = document.createElementNS(SVG_NS, tag);
899
- for (const [key, value] of Object.entries(props)) {
900
- if (key === "nodes") continue;
901
- if (typeof value === "function" && key.startsWith("on")) {
902
- el.addEventListener(key.slice(2).toLowerCase(), value);
903
- } else if (value != null) {
904
- el.setAttribute(key, String(value));
905
- }
906
- }
907
- for (const child of nodes) {
908
- if (typeof child === "string") {
909
- el.appendChild(document.createTextNode(child));
910
- } else if (child instanceof Node) {
911
- el.appendChild(child);
912
- }
913
- }
914
- return el;
915
- }
916
-
917
- export {
918
- required,
919
- minLength,
920
- maxLength,
921
- matchesPattern,
922
- email,
923
- min,
924
- max,
925
- custom,
926
- bindField,
927
- form,
928
- VirtualList,
929
- intersection,
930
- lazyLoad,
931
- inputMask,
932
- phoneMask,
933
- dateMask,
934
- creditCardMask,
935
- timeMask,
936
- ssnMask,
937
- zipMask,
938
- aria,
939
- focus,
940
- FocusTrap,
941
- hotkey,
942
- announce,
943
- scopedStyle,
944
- withScopedStyle,
945
- removeScopedStyle,
946
- bindAttrs,
947
- bindBoolAttr,
948
- bindData,
949
- dialog,
950
- toast,
951
- infiniteScroll,
952
- pagination,
953
- eventBus,
954
- defineElement,
955
- svgElement
956
- };