@vertz/ui 0.2.0 → 0.2.2

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 (36) hide show
  1. package/README.md +339 -857
  2. package/dist/css/public.d.ts +24 -27
  3. package/dist/css/public.js +5 -1
  4. package/dist/form/public.d.ts +94 -38
  5. package/dist/form/public.js +5 -3
  6. package/dist/index.d.ts +754 -167
  7. package/dist/index.js +606 -84
  8. package/dist/internals.d.ts +192 -23
  9. package/dist/internals.js +151 -102
  10. package/dist/jsx-runtime/index.d.ts +44 -17
  11. package/dist/jsx-runtime/index.js +26 -7
  12. package/dist/query/public.d.ts +73 -7
  13. package/dist/query/public.js +12 -4
  14. package/dist/router/public.d.ts +199 -26
  15. package/dist/router/public.js +22 -7
  16. package/dist/shared/chunk-0xcmwgdb.js +288 -0
  17. package/dist/shared/{chunk-j8vzvne3.js → chunk-9e92w0wt.js} +4 -1
  18. package/dist/shared/chunk-g4rch80a.js +33 -0
  19. package/dist/shared/chunk-hh0dhmb4.js +528 -0
  20. package/dist/shared/{chunk-pgymxpn1.js → chunk-hrd0mft1.js} +136 -34
  21. package/dist/shared/chunk-jrtrk5z4.js +125 -0
  22. package/dist/shared/chunk-ka5ked7n.js +188 -0
  23. package/dist/shared/chunk-n91rwj2r.js +483 -0
  24. package/dist/shared/chunk-prj7nm08.js +67 -0
  25. package/dist/shared/chunk-q6cpe5k7.js +230 -0
  26. package/dist/shared/{chunk-f1ynwam4.js → chunk-qacth5ah.js} +162 -36
  27. package/dist/shared/chunk-ryb49346.js +374 -0
  28. package/dist/shared/chunk-v3yyf79g.js +48 -0
  29. package/dist/test/index.d.ts +67 -6
  30. package/dist/test/index.js +4 -3
  31. package/package.json +14 -9
  32. package/dist/shared/chunk-bp3v6s9j.js +0 -62
  33. package/dist/shared/chunk-d8h2eh8d.js +0 -141
  34. package/dist/shared/chunk-tsdpgmks.js +0 -98
  35. package/dist/shared/chunk-xd9d7q5p.js +0 -115
  36. package/dist/shared/chunk-zbbvx05f.js +0 -202
@@ -0,0 +1,288 @@
1
+ import {
2
+ __classList,
3
+ __on
4
+ } from "./chunk-v3yyf79g.js";
5
+ import {
6
+ __append,
7
+ __element,
8
+ __enterChildren,
9
+ __exitChildren,
10
+ __staticText,
11
+ getIsHydrating
12
+ } from "./chunk-ryb49346.js";
13
+ import {
14
+ _tryOnCleanup,
15
+ createContext,
16
+ domEffect,
17
+ popScope,
18
+ pushScope,
19
+ runCleanups,
20
+ signal,
21
+ untrack,
22
+ useContext
23
+ } from "./chunk-hrd0mft1.js";
24
+
25
+ // src/router/link.ts
26
+ var DANGEROUS_SCHEMES = ["javascript:", "data:", "vbscript:"];
27
+ function isSafeUrl(url) {
28
+ const normalized = url.replace(/\s/g, "").toLowerCase();
29
+ if (normalized.startsWith("//"))
30
+ return false;
31
+ for (const scheme of DANGEROUS_SCHEMES) {
32
+ if (normalized.startsWith(scheme))
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ function createLink(currentPath, navigate, factoryOptions) {
38
+ return function Link({
39
+ href,
40
+ children,
41
+ activeClass,
42
+ className,
43
+ prefetch
44
+ }) {
45
+ const safeHref = isSafeUrl(href) ? href : "#";
46
+ const handleClick = (event) => {
47
+ const mouseEvent = event;
48
+ if (mouseEvent.ctrlKey || mouseEvent.metaKey || mouseEvent.shiftKey || mouseEvent.altKey) {
49
+ return;
50
+ }
51
+ mouseEvent.preventDefault();
52
+ navigate(safeHref);
53
+ };
54
+ const props = { href: safeHref };
55
+ if (className) {
56
+ props.class = className;
57
+ }
58
+ const el = __element("a", props);
59
+ __on(el, "click", handleClick);
60
+ __enterChildren(el);
61
+ if (typeof children === "function") {
62
+ const result = children();
63
+ if (typeof result === "string") {
64
+ __append(el, __staticText(result));
65
+ } else {
66
+ __append(el, result);
67
+ }
68
+ } else {
69
+ __append(el, __staticText(children));
70
+ }
71
+ __exitChildren();
72
+ if (activeClass) {
73
+ __classList(el, {
74
+ [activeClass]: () => currentPath.value === safeHref
75
+ });
76
+ }
77
+ if (prefetch === "hover" && factoryOptions?.onPrefetch) {
78
+ let prefetched = false;
79
+ const triggerPrefetch = () => {
80
+ if (prefetched)
81
+ return;
82
+ prefetched = true;
83
+ factoryOptions.onPrefetch?.(safeHref);
84
+ };
85
+ __on(el, "mouseenter", triggerPrefetch);
86
+ __on(el, "focus", triggerPrefetch);
87
+ }
88
+ return el;
89
+ };
90
+ }
91
+
92
+ // src/router/router-context.ts
93
+ var RouterContext = createContext();
94
+ function useRouter() {
95
+ const router = useContext(RouterContext);
96
+ if (!router) {
97
+ throw new Error("useRouter() must be called within RouterContext.Provider");
98
+ }
99
+ return router;
100
+ }
101
+ function useParams() {
102
+ const router = useContext(RouterContext);
103
+ if (!router) {
104
+ throw new Error("useParams() must be called within RouterContext.Provider");
105
+ }
106
+ return router.current?.params ?? {};
107
+ }
108
+
109
+ // src/router/outlet.ts
110
+ var OutletContext = createContext();
111
+ function Outlet() {
112
+ const ctx = useContext(OutletContext);
113
+ if (!ctx) {
114
+ return document.createComment("outlet:empty");
115
+ }
116
+ const container = __element("div");
117
+ let childCleanups = [];
118
+ let renderGen = 0;
119
+ let isFirstHydrationRender = getIsHydrating();
120
+ __enterChildren(container);
121
+ const dispose = domEffect(() => {
122
+ const factory = ctx.childComponent;
123
+ untrack(() => {
124
+ runCleanups(childCleanups);
125
+ if (isFirstHydrationRender) {
126
+ isFirstHydrationRender = false;
127
+ } else {
128
+ while (container.firstChild) {
129
+ container.removeChild(container.firstChild);
130
+ }
131
+ }
132
+ const gen = ++renderGen;
133
+ childCleanups = pushScope();
134
+ if (factory) {
135
+ const result = factory();
136
+ if (result instanceof Promise) {
137
+ const router = ctx.router;
138
+ popScope();
139
+ result.then((mod) => {
140
+ if (gen !== renderGen)
141
+ return;
142
+ childCleanups = pushScope();
143
+ RouterContext.Provider(router, () => {
144
+ const node = mod.default();
145
+ __append(container, node);
146
+ });
147
+ popScope();
148
+ });
149
+ } else {
150
+ __append(container, result);
151
+ popScope();
152
+ }
153
+ } else {
154
+ popScope();
155
+ }
156
+ });
157
+ });
158
+ __exitChildren();
159
+ _tryOnCleanup(() => {
160
+ runCleanups(childCleanups);
161
+ dispose();
162
+ });
163
+ return container;
164
+ }
165
+
166
+ // src/router/router-view.ts
167
+ function RouterView({ router, fallback }) {
168
+ const container = __element("div");
169
+ let isFirstHydrationRender = getIsHydrating();
170
+ let renderGen = 0;
171
+ let pageCleanups = [];
172
+ let prevLevels = [];
173
+ __enterChildren(container);
174
+ const dispose = domEffect(() => {
175
+ const match = router.current.value;
176
+ untrack(() => {
177
+ const gen = ++renderGen;
178
+ const newMatched = match?.matched ?? [];
179
+ const minLen = Math.min(prevLevels.length, newMatched.length);
180
+ let divergeAt = 0;
181
+ for (divergeAt = 0;divergeAt < minLen; divergeAt++) {
182
+ if (prevLevels[divergeAt].route !== newMatched[divergeAt].route)
183
+ break;
184
+ }
185
+ if (prevLevels.length > 0 && divergeAt === prevLevels.length && divergeAt === newMatched.length) {
186
+ return;
187
+ }
188
+ if (divergeAt > 0 && newMatched.length > 0) {
189
+ const newLevels = buildLevels(newMatched);
190
+ const newChildFactory = buildInsideOutFactory(newMatched, newLevels, divergeAt, router);
191
+ const parentLevel = prevLevels[divergeAt - 1];
192
+ if (parentLevel.childSignal) {
193
+ parentLevel.childSignal.value = newChildFactory;
194
+ }
195
+ prevLevels = [...prevLevels.slice(0, divergeAt), ...newLevels.slice(divergeAt)];
196
+ return;
197
+ }
198
+ runCleanups(pageCleanups);
199
+ const doRender = () => {
200
+ if (!isFirstHydrationRender) {
201
+ while (container.firstChild) {
202
+ container.removeChild(container.firstChild);
203
+ }
204
+ }
205
+ isFirstHydrationRender = false;
206
+ pageCleanups = pushScope();
207
+ if (!match) {
208
+ prevLevels = [];
209
+ if (fallback) {
210
+ container.appendChild(fallback());
211
+ }
212
+ popScope();
213
+ return;
214
+ }
215
+ const levels = buildLevels(newMatched);
216
+ const rootFactory = buildInsideOutFactory(newMatched, levels, 0, router);
217
+ RouterContext.Provider(router, () => {
218
+ const result = rootFactory();
219
+ if (result instanceof Promise) {
220
+ result.then((mod) => {
221
+ if (gen !== renderGen)
222
+ return;
223
+ RouterContext.Provider(router, () => {
224
+ const node = mod.default();
225
+ container.appendChild(node);
226
+ });
227
+ });
228
+ } else {
229
+ __append(container, result);
230
+ }
231
+ });
232
+ prevLevels = levels;
233
+ popScope();
234
+ };
235
+ doRender();
236
+ });
237
+ });
238
+ __exitChildren();
239
+ _tryOnCleanup(() => {
240
+ runCleanups(pageCleanups);
241
+ dispose();
242
+ });
243
+ return container;
244
+ }
245
+ function buildLevels(matched) {
246
+ return matched.map((m, i) => ({
247
+ childSignal: i < matched.length - 1 ? signal(undefined) : undefined,
248
+ route: m.route
249
+ }));
250
+ }
251
+ function buildInsideOutFactory(matched, levels, startAt, router) {
252
+ let factory = matched[matched.length - 1].route.component;
253
+ for (let i = matched.length - 2;i >= startAt; i--) {
254
+ const level = levels[i];
255
+ const childFactory = factory;
256
+ level.childSignal.value = childFactory;
257
+ const parentRoute = level.route;
258
+ const cs = level.childSignal;
259
+ factory = () => {
260
+ let result;
261
+ OutletContext.Provider({ childComponent: cs, router }, () => {
262
+ result = parentRoute.component();
263
+ });
264
+ return result;
265
+ };
266
+ }
267
+ return factory;
268
+ }
269
+
270
+ // src/router/search-params.ts
271
+ function parseSearchParams(urlParams, schema) {
272
+ const raw = {};
273
+ for (const [key, value] of urlParams.entries()) {
274
+ raw[key] = value;
275
+ }
276
+ if (schema) {
277
+ const result = schema.parse(raw);
278
+ if (result.ok)
279
+ return result.data;
280
+ return raw;
281
+ }
282
+ return raw;
283
+ }
284
+ function useSearchParams(searchSignal) {
285
+ return searchSignal.value;
286
+ }
287
+
288
+ export { createLink, RouterContext, useRouter, useParams, OutletContext, Outlet, RouterView, parseSearchParams, useSearchParams };
@@ -67,7 +67,10 @@ function matchRoute(routes, url) {
67
67
  for (const [key, value] of searchParams.entries()) {
68
68
  raw[key] = value;
69
69
  }
70
- search = m.route.searchParams.parse(raw);
70
+ const parseResult = m.route.searchParams.parse(raw);
71
+ if (parseResult.ok) {
72
+ search = parseResult.data;
73
+ }
71
74
  break;
72
75
  }
73
76
  }
@@ -0,0 +1,33 @@
1
+ // src/dom/dom-adapter.ts
2
+ function createDOMAdapter() {
3
+ return {
4
+ createElement: (tag) => document.createElement(tag),
5
+ createElementNS: (ns, tag) => document.createElementNS(ns, tag),
6
+ createTextNode: (text) => document.createTextNode(text),
7
+ createComment: (text) => document.createComment(text),
8
+ createDocumentFragment: () => document.createDocumentFragment(),
9
+ isNode: (value) => typeof Node !== "undefined" && value instanceof Node
10
+ };
11
+ }
12
+
13
+ // src/dom/adapter.ts
14
+ var RENDER_NODE_BRAND = Symbol.for("vertz:render-node");
15
+ function isRenderNode(value) {
16
+ if (value == null || typeof value !== "object")
17
+ return false;
18
+ if (RENDER_NODE_BRAND in value)
19
+ return true;
20
+ return typeof Node !== "undefined" && value instanceof Node;
21
+ }
22
+ var currentAdapter = null;
23
+ function getAdapter() {
24
+ if (!currentAdapter) {
25
+ currentAdapter = createDOMAdapter();
26
+ }
27
+ return currentAdapter;
28
+ }
29
+ function setAdapter(adapter) {
30
+ currentAdapter = adapter;
31
+ }
32
+
33
+ export { createDOMAdapter, RENDER_NODE_BRAND, isRenderNode, getAdapter, setAdapter };