@epoch32/visage 0.0.0-stage → 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 (135) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +110 -2
  3. package/dist/src/api/index.js +4002 -0
  4. package/dist/src/charts/index.js +2717 -0
  5. package/dist/src/devtools/index.js +4677 -0
  6. package/dist/src/dom/index.js +1550 -0
  7. package/dist/src/form/index.js +1415 -0
  8. package/dist/src/index.js +11826 -0
  9. package/dist/src/jsx-runtime/index.js +1630 -0
  10. package/dist/src/query/index.js +2422 -0
  11. package/dist/src/router/index.js +1856 -0
  12. package/dist/src/rpc/index.js +3484 -0
  13. package/dist/src/server/index.js +1173 -0
  14. package/dist/src/signals/index.js +1077 -0
  15. package/dist/src/style/index.js +2340 -0
  16. package/dist/src/template/index.js +1149 -0
  17. package/dist/src/ui/index.js +4155 -0
  18. package/dist/src/virtual/index.js +1955 -0
  19. package/dist/src/vite/index.js +984 -0
  20. package/package.json +140 -4
  21. package/src/api/client.ts +371 -0
  22. package/src/api/file-router.ts +183 -0
  23. package/src/api/handler.ts +326 -0
  24. package/src/api/index.ts +71 -0
  25. package/src/api/middleware.ts +54 -0
  26. package/src/api/pragma.ts +155 -0
  27. package/src/api/procedure.ts +172 -0
  28. package/src/api/types.ts +249 -0
  29. package/src/charts/Area.tsx +111 -0
  30. package/src/charts/Axis.tsx +126 -0
  31. package/src/charts/Bar.tsx +86 -0
  32. package/src/charts/CartesianGrid.tsx +72 -0
  33. package/src/charts/Chart.tsx +269 -0
  34. package/src/charts/Cursor.tsx +42 -0
  35. package/src/charts/Legend.tsx +56 -0
  36. package/src/charts/Line.tsx +106 -0
  37. package/src/charts/Pie.tsx +88 -0
  38. package/src/charts/Tooltip.tsx +127 -0
  39. package/src/charts/context.ts +30 -0
  40. package/src/charts/index.ts +14 -0
  41. package/src/charts/path.ts +155 -0
  42. package/src/charts/scale.ts +133 -0
  43. package/src/charts/types.ts +50 -0
  44. package/src/devtools/DomTab.tsx +134 -0
  45. package/src/devtools/GraphInspector.tsx +196 -0
  46. package/src/devtools/GraphTab.tsx +315 -0
  47. package/src/devtools/QueryTab.tsx +200 -0
  48. package/src/devtools/RpcTab.tsx +190 -0
  49. package/src/devtools/SignalsTab.tsx +129 -0
  50. package/src/devtools/component.tsx +243 -0
  51. package/src/devtools/highlighter.ts +134 -0
  52. package/src/devtools/hub.ts +175 -0
  53. package/src/devtools/index.ts +20 -0
  54. package/src/devtools/styles.ts +313 -0
  55. package/src/devtools/types.ts +45 -0
  56. package/src/dom/async.ts +232 -0
  57. package/src/dom/control-flow.ts +353 -0
  58. package/src/dom/index.ts +32 -0
  59. package/src/dom/lazy.ts +82 -0
  60. package/src/dom/render.ts +286 -0
  61. package/src/dom/resource.ts +120 -0
  62. package/src/form/form.ts +218 -0
  63. package/src/form/index.ts +17 -0
  64. package/src/form/schema.ts +299 -0
  65. package/src/index.ts +413 -0
  66. package/src/jsx-dev-runtime/index.ts +1 -0
  67. package/src/jsx-runtime/index.ts +112 -0
  68. package/src/jsx-runtime/jsx.d.ts +278 -0
  69. package/src/query/create-mutation.ts +64 -0
  70. package/src/query/create-query.ts +426 -0
  71. package/src/query/focus-manager.ts +68 -0
  72. package/src/query/index.ts +63 -0
  73. package/src/query/mutation-cache.ts +138 -0
  74. package/src/query/online-manager.ts +67 -0
  75. package/src/query/query-cache.ts +369 -0
  76. package/src/query/query-client.ts +248 -0
  77. package/src/query/types.ts +221 -0
  78. package/src/query/utils.ts +132 -0
  79. package/src/router/index.ts +19 -0
  80. package/src/router/router.tsx +352 -0
  81. package/src/rpc/client.ts +317 -0
  82. package/src/rpc/error.ts +70 -0
  83. package/src/rpc/index.ts +52 -0
  84. package/src/rpc/procedure.ts +88 -0
  85. package/src/rpc/router.ts +105 -0
  86. package/src/rpc/server.ts +511 -0
  87. package/src/rpc/types.ts +328 -0
  88. package/src/server/hydrate.ts +21 -0
  89. package/src/server/index.ts +10 -0
  90. package/src/server/render-to-stream.ts +31 -0
  91. package/src/server/render-to-string.ts +125 -0
  92. package/src/signals/computed.ts +217 -0
  93. package/src/signals/context.ts +89 -0
  94. package/src/signals/effect.ts +161 -0
  95. package/src/signals/index.ts +57 -0
  96. package/src/signals/scope.ts +132 -0
  97. package/src/signals/signal.ts +203 -0
  98. package/src/signals/store.ts +163 -0
  99. package/src/signals/system.ts +124 -0
  100. package/src/signals/types.ts +64 -0
  101. package/src/style/component.tsx +122 -0
  102. package/src/style/create-style.ts +229 -0
  103. package/src/style/cx.ts +75 -0
  104. package/src/style/hash.ts +19 -0
  105. package/src/style/index.ts +8 -0
  106. package/src/style/layout.tsx +406 -0
  107. package/src/style/manager.ts +87 -0
  108. package/src/style/parser.ts +257 -0
  109. package/src/style/scale.ts +237 -0
  110. package/src/template/index.ts +4 -0
  111. package/src/template/template.ts +126 -0
  112. package/src/ui/accordion.tsx +286 -0
  113. package/src/ui/command-dialog.tsx +49 -0
  114. package/src/ui/command.tsx +400 -0
  115. package/src/ui/data-table.tsx +322 -0
  116. package/src/ui/dialog.tsx +362 -0
  117. package/src/ui/dropdown-menu.tsx +381 -0
  118. package/src/ui/icon.tsx +69 -0
  119. package/src/ui/index.ts +138 -0
  120. package/src/ui/layout.tsx +13 -0
  121. package/src/ui/popover.tsx +249 -0
  122. package/src/ui/switch.tsx +114 -0
  123. package/src/ui/tabs.tsx +297 -0
  124. package/src/ui/toast.tsx +280 -0
  125. package/src/ui/tooltip.tsx +262 -0
  126. package/src/ui/utils.ts +110 -0
  127. package/src/virtual/index.ts +12 -0
  128. package/src/virtual/virtual-list.tsx +185 -0
  129. package/src/virtual/virtualizer.ts +274 -0
  130. package/src/vite/hmr.ts +38 -0
  131. package/src/vite/index.ts +3 -0
  132. package/src/vite/lucide.ts +124 -0
  133. package/src/vite/plugin.ts +102 -0
  134. package/src/vite/rpc-middleware.ts +82 -0
  135. package/src/vite/types.ts +65 -0
@@ -0,0 +1,229 @@
1
+ import type * as CSS from "csstype";
2
+ import { onCleanup } from "../signals";
3
+ import { type ClassValue, cx } from "./cx";
4
+ import { getScopeId } from "./hash";
5
+ import { styleManager } from "./manager";
6
+ import { scopeCSS } from "./parser";
7
+ import { formatStyleProp } from "./scale";
8
+
9
+ /**
10
+ * Standard CSS Properties interface with full TypeScript & VS Code IntelliSense,
11
+ * supporting nested pseudo-classes, descendant selectors, and custom CSS variables.
12
+ */
13
+ export type CSSProperties = CSS.Properties<string | number> & {
14
+ [key: `&${string}`]: CSSProperties | undefined;
15
+ [key: `.${string}`]: CSSProperties | undefined;
16
+ [key: `:${string}`]: CSSProperties | undefined;
17
+ [key: `@media${string}`]: CSSProperties | undefined;
18
+ [key: `@keyframes${string}`]: Record<string, CSSProperties> | undefined;
19
+ [key: `${number}%`]: CSSProperties | undefined;
20
+ from?: CSSProperties;
21
+ to?: CSSProperties;
22
+ [customProp: `--${string}`]: string | number | undefined;
23
+ };
24
+
25
+ export type StyleDefinition = Record<string, CSSProperties>;
26
+
27
+ export type StyleClasses<T extends string = string> = {
28
+ [K in T]: string;
29
+ } & Record<string, any> & {
30
+ scope: string;
31
+ scopeAttr: string;
32
+ css: string;
33
+ cx: (...args: ClassValue[]) => string;
34
+ };
35
+
36
+ function formatCSSValue(prop: string, val: any): string {
37
+ return formatStyleProp(prop, val);
38
+ }
39
+
40
+ /**
41
+ * Convert a JavaScript object style dictionary into standard CSS
42
+ */
43
+ export function objectToCSS(classes: Record<string, any>): string {
44
+ let css = "";
45
+ for (const [selector, rules] of Object.entries(classes)) {
46
+ if (typeof rules !== "object" || rules === null) continue;
47
+ const sel =
48
+ selector.startsWith(".") ||
49
+ selector.startsWith("@") ||
50
+ selector.startsWith(":") ||
51
+ selector.includes(" ") ||
52
+ selector === "*"
53
+ ? selector
54
+ : `.${selector}`;
55
+
56
+ let mainRules = "";
57
+ let nestedRules = "";
58
+
59
+ for (const [prop, val] of Object.entries(rules)) {
60
+ if (typeof val === "object" && val !== null) {
61
+ const nestedSel = prop.startsWith("&")
62
+ ? prop.replace(/&/g, sel)
63
+ : prop.startsWith(":")
64
+ ? `${sel}${prop}`
65
+ : `${sel} ${prop}`;
66
+
67
+ nestedRules += `${nestedSel} {\n`;
68
+ for (const [np, nv] of Object.entries(val as Record<string, any>)) {
69
+ if (nv !== undefined && nv !== null) {
70
+ const kebab = np.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
71
+ nestedRules += ` ${kebab}: ${formatCSSValue(np, nv)};\n`;
72
+ }
73
+ }
74
+ nestedRules += `}\n`;
75
+ } else if (val !== undefined && val !== null) {
76
+ const kebab = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
77
+ mainRules += ` ${kebab}: ${formatCSSValue(prop, val)};\n`;
78
+ }
79
+ }
80
+
81
+ if (mainRules) {
82
+ css += `${sel} {\n${mainRules}}\n`;
83
+ }
84
+ if (nestedRules) {
85
+ css += nestedRules;
86
+ }
87
+ }
88
+ return css;
89
+ }
90
+
91
+ /**
92
+ * Define scoped CSS styles with type-safe class name mappings
93
+ *
94
+ * Supports tagged template literals, string CSS, or JavaScript style objects:
95
+ *
96
+ * 1. Object syntax with full VS Code CSS IntelliSense:
97
+ * ```tsx
98
+ * const styles = createStyle({
99
+ * card: { background: "var(--card-bg)", padding: "16px", display: "flex" },
100
+ * button: { background: "var(--primary)", "&:hover": { background: "var(--primary-hover)" } }
101
+ * });
102
+ * ```
103
+ *
104
+ * 2. Tagged template literal syntax:
105
+ * ```tsx
106
+ * const styles = createStyle`
107
+ * .card { padding: 16px; border-radius: 8px; }
108
+ * .active { color: var(--primary); }
109
+ * `;
110
+ * ```
111
+ */
112
+ export function createStyle<T extends string = string>(
113
+ templateOrObject: string | TemplateStringsArray | StyleDefinition,
114
+ ...valuesOrOptions: any[]
115
+ ): StyleClasses<T> {
116
+ let cssInput = "";
117
+ let options: { passToChildren?: boolean; id?: string } | undefined;
118
+
119
+ if (typeof templateOrObject === "object" && !Array.isArray(templateOrObject)) {
120
+ // Object style definition
121
+ cssInput = objectToCSS(templateOrObject);
122
+ options = valuesOrOptions[0];
123
+ } else if (typeof templateOrObject === "string") {
124
+ cssInput = templateOrObject;
125
+ options = valuesOrOptions[0];
126
+ } else {
127
+ const template = templateOrObject as unknown as TemplateStringsArray;
128
+ for (let i = 0; i < template.length; i++) {
129
+ cssInput += template[i];
130
+ if (i < valuesOrOptions.length) {
131
+ cssInput += String(valuesOrOptions[i]);
132
+ }
133
+ }
134
+ }
135
+
136
+ const scopeId = options?.id ?? getScopeId(cssInput);
137
+ const scopeAttr = `data-${scopeId}`;
138
+ const classMap: Record<string, string> = {};
139
+
140
+ // Extract class names defined in the CSS
141
+ const classRegex = /\.([a-zA-Z0-9_-]+)/g;
142
+ let match: RegExpExecArray | null = classRegex.exec(cssInput);
143
+ while (match !== null) {
144
+ const className = match[1];
145
+ if (className && !classMap[className]) {
146
+ // Scoped class name
147
+ classMap[className] = `${className}_${scopeId}`;
148
+ }
149
+ match = classRegex.exec(cssInput);
150
+ }
151
+
152
+ // Rewrite CSS classes to use scoped class names
153
+ let transformedCSS = cssInput;
154
+ for (const [orig, scoped] of Object.entries(classMap)) {
155
+ const replaceRegex = new RegExp(`\\.${orig}\\b`, "g");
156
+ transformedCSS = transformedCSS.replace(replaceRegex, `.${scoped}`);
157
+ }
158
+
159
+ const finalScopedCSS = scopeCSS(transformedCSS, {
160
+ scopeId,
161
+ passToChildren: options?.passToChildren ?? false
162
+ });
163
+
164
+ // Inject into StyleManager
165
+ styleManager.inject(scopeId, finalScopedCSS);
166
+
167
+ const result: any = {
168
+ ...classMap,
169
+ scope: scopeId,
170
+ scopeAttr,
171
+ css: finalScopedCSS,
172
+ cx: (...args: ClassValue[]) => cx(...args)
173
+ };
174
+
175
+ return result as StyleClasses<T>;
176
+ }
177
+
178
+ /**
179
+ * Tagged template for defining a single scoped CSS class
180
+ */
181
+ export function css(strings: TemplateStringsArray, ...values: any[]): string {
182
+ let rawCSS = "";
183
+ for (let i = 0; i < strings.length; i++) {
184
+ rawCSS += strings[i];
185
+ if (i < values.length) {
186
+ rawCSS += String(values[i]);
187
+ }
188
+ }
189
+
190
+ const scopeId = getScopeId(rawCSS, "cls");
191
+ const className = `visage_${scopeId}`;
192
+
193
+ // Wrap inside class selector
194
+ const fullCSS = rawCSS.includes("&")
195
+ ? rawCSS.replace(/&/g, `.${className}`)
196
+ : `.${className} { ${rawCSS} }`;
197
+
198
+ const scoped = scopeCSS(fullCSS, { scopeId });
199
+ styleManager.inject(scopeId, scoped);
200
+
201
+ return className;
202
+ }
203
+
204
+ /**
205
+ * Hook to inject dynamic or component-level CSS with automatic cleanup
206
+ */
207
+ export function useStyle(
208
+ cssInput: string | StyleDefinition | (() => string | StyleDefinition),
209
+ options?: { passToChildren?: boolean; id?: string }
210
+ ): string {
211
+ const getRaw = () => {
212
+ const val = typeof cssInput === "function" ? cssInput() : cssInput;
213
+ return typeof val === "object" ? objectToCSS(val) : val;
214
+ };
215
+
216
+ const raw = getRaw();
217
+ const scopeId = options?.id ?? getScopeId(raw);
218
+ const scopedCSS = scopeCSS(raw, {
219
+ scopeId,
220
+ passToChildren: options?.passToChildren ?? false
221
+ });
222
+
223
+ const cleanup = styleManager.inject(scopeId, scopedCSS);
224
+ onCleanup(() => {
225
+ cleanup();
226
+ });
227
+
228
+ return scopeId;
229
+ }
@@ -0,0 +1,75 @@
1
+ export type ClassValue =
2
+ | string
3
+ | number
4
+ | boolean
5
+ | null
6
+ | undefined
7
+ | (() => any)
8
+ | ClassValue[]
9
+ | Record<string, any>;
10
+
11
+ /**
12
+ * Check if a class value tree contains any reactive signal or function getters
13
+ */
14
+ export function hasReactiveClass(val: any): boolean {
15
+ if (typeof val === "function") return true;
16
+ if (Array.isArray(val)) {
17
+ for (let i = 0; i < val.length; i++) {
18
+ if (hasReactiveClass(val[i])) return true;
19
+ }
20
+ return false;
21
+ }
22
+ if (typeof val === "object" && val !== null) {
23
+ for (const k in val) {
24
+ if (typeof val[k] === "function") return true;
25
+ }
26
+ }
27
+ return false;
28
+ }
29
+
30
+ /**
31
+ * Normalize dynamic classes from strings, numbers, arrays, and objects
32
+ */
33
+ export function normalizeClass(val: any): string {
34
+ if (!val) return "";
35
+ if (typeof val === "function") return normalizeClass(val());
36
+ if (typeof val === "string") return val.trim();
37
+ if (typeof val === "number") return String(val);
38
+
39
+ if (Array.isArray(val)) {
40
+ let res = "";
41
+ for (let i = 0; i < val.length; i++) {
42
+ const item = typeof val[i] === "function" ? val[i]() : val[i];
43
+ const itemStr = normalizeClass(item);
44
+ if (itemStr) {
45
+ res = res ? `${res} ${itemStr}` : itemStr;
46
+ }
47
+ }
48
+ return res;
49
+ }
50
+
51
+ if (typeof val === "object") {
52
+ let res = "";
53
+ for (const key in val) {
54
+ const condition = typeof val[key] === "function" ? val[key]() : val[key];
55
+ if (condition) {
56
+ res = res ? `${res} ${key}` : key;
57
+ }
58
+ }
59
+ return res;
60
+ }
61
+
62
+ return "";
63
+ }
64
+
65
+ /**
66
+ * Flexible classnames utility for combining conditional classes
67
+ *
68
+ * Example:
69
+ * ```ts
70
+ * cx("btn", { active: isActive(), disabled: !isEnabled() }, ["extra-1", extraClass])
71
+ * ```
72
+ */
73
+ export function cx(...args: ClassValue[]): string {
74
+ return normalizeClass(args);
75
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Fast 32-bit FNV-1a deterministic string hashing algorithm
3
+ */
4
+ export function hashString(str: string): string {
5
+ let hash = 0x811c9dc5;
6
+ for (let i = 0; i < str.length; i++) {
7
+ hash ^= str.charCodeAt(i);
8
+ hash = Math.imul(hash, 0x01000193);
9
+ }
10
+ return (hash >>> 0).toString(36);
11
+ }
12
+
13
+ /**
14
+ * Generate a deterministic scope identifier for CSS blocks
15
+ */
16
+ export function getScopeId(css: string, prefix = "v"): string {
17
+ const hash = hashString(css.trim());
18
+ return `${prefix}-${hash}`;
19
+ }
@@ -0,0 +1,8 @@
1
+ export * from "./component";
2
+ export * from "./create-style";
3
+ export * from "./cx";
4
+ export * from "./hash";
5
+ export * from "./layout";
6
+ export * from "./manager";
7
+ export * from "./parser";
8
+ export * from "./scale";