fynixui 1.0.12 → 1.0.13

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.
@@ -1 +1,359 @@
1
- "use strict";
1
+ import { Fynix } from "../runtime.js";
2
+ const VARIANT_THEMES = {
3
+ primary: {
4
+ headerBg: "rgba(13,110,253,0.08)",
5
+ headerColor: "#0d6efd",
6
+ headerBorder: "rgba(13,110,253,0.2)",
7
+ rowBorder: "rgba(13,110,253,0.09)",
8
+ rowHoverBg: "rgba(13,110,253,0.04)",
9
+ stripeBg: "rgba(13,110,253,0.03)",
10
+ accentBg: "#0d6efd",
11
+ accentColor: "#fff",
12
+ accentHoverBg: "#0b5ed7",
13
+ accentBorder: "#0d6efd",
14
+ },
15
+ secondary: {
16
+ headerBg: "rgba(108,117,125,0.08)",
17
+ headerColor: "#6c757d",
18
+ headerBorder: "rgba(108,117,125,0.2)",
19
+ rowBorder: "rgba(108,117,125,0.09)",
20
+ rowHoverBg: "rgba(108,117,125,0.04)",
21
+ stripeBg: "rgba(108,117,125,0.03)",
22
+ accentBg: "#6c757d",
23
+ accentColor: "#fff",
24
+ accentHoverBg: "#5c636a",
25
+ accentBorder: "#6c757d",
26
+ },
27
+ success: {
28
+ headerBg: "rgba(25,135,84,0.08)",
29
+ headerColor: "#198754",
30
+ headerBorder: "rgba(25,135,84,0.2)",
31
+ rowBorder: "rgba(25,135,84,0.09)",
32
+ rowHoverBg: "rgba(25,135,84,0.04)",
33
+ stripeBg: "rgba(25,135,84,0.03)",
34
+ accentBg: "#198754",
35
+ accentColor: "#fff",
36
+ accentHoverBg: "#157347",
37
+ accentBorder: "#198754",
38
+ },
39
+ danger: {
40
+ headerBg: "rgba(220,53,69,0.08)",
41
+ headerColor: "#dc3545",
42
+ headerBorder: "rgba(220,53,69,0.2)",
43
+ rowBorder: "rgba(220,53,69,0.09)",
44
+ rowHoverBg: "rgba(220,53,69,0.04)",
45
+ stripeBg: "rgba(220,53,69,0.03)",
46
+ accentBg: "#dc3545",
47
+ accentColor: "#fff",
48
+ accentHoverBg: "#bb2d3b",
49
+ accentBorder: "#dc3545",
50
+ },
51
+ warning: {
52
+ headerBg: "rgba(255,193,7,0.10)",
53
+ headerColor: "#856404",
54
+ headerBorder: "rgba(255,193,7,0.3)",
55
+ rowBorder: "rgba(255,193,7,0.12)",
56
+ rowHoverBg: "rgba(255,193,7,0.05)",
57
+ stripeBg: "rgba(255,193,7,0.04)",
58
+ accentBg: "#ffc107",
59
+ accentColor: "#212529",
60
+ accentHoverBg: "#ffca2c",
61
+ accentBorder: "#ffc107",
62
+ },
63
+ info: {
64
+ headerBg: "rgba(13,202,240,0.08)",
65
+ headerColor: "#055160",
66
+ headerBorder: "rgba(13,202,240,0.2)",
67
+ rowBorder: "rgba(13,202,240,0.09)",
68
+ rowHoverBg: "rgba(13,202,240,0.04)",
69
+ stripeBg: "rgba(13,202,240,0.03)",
70
+ accentBg: "#0dcaf0",
71
+ accentColor: "#212529",
72
+ accentHoverBg: "#31d2f2",
73
+ accentBorder: "#0dcaf0",
74
+ },
75
+ light: {
76
+ headerBg: "#f8f9fa",
77
+ headerColor: "#495057",
78
+ headerBorder: "#dee2e6",
79
+ rowBorder: "#e9ecef",
80
+ rowHoverBg: "#f1f3f5",
81
+ stripeBg: "#f8f9fa",
82
+ accentBg: "#f8f9fa",
83
+ accentColor: "#212529",
84
+ accentHoverBg: "#e2e6ea",
85
+ accentBorder: "#dee2e6",
86
+ },
87
+ dark: {
88
+ headerBg: "rgba(33,37,41,0.07)",
89
+ headerColor: "inherit",
90
+ headerBorder: "rgba(33,37,41,0.15)",
91
+ rowBorder: "rgba(33,37,41,0.08)",
92
+ rowHoverBg: "rgba(33,37,41,0.04)",
93
+ stripeBg: "rgba(33,37,41,0.03)",
94
+ accentBg: "#212529",
95
+ accentColor: "#fff",
96
+ accentHoverBg: "#424649",
97
+ accentBorder: "#212529",
98
+ },
99
+ };
100
+ const OUTLINE_THEMES = Object.fromEntries(Object.entries(VARIANT_THEMES).map(([k, v]) => [
101
+ k,
102
+ {
103
+ ...v,
104
+ headerBg: "transparent",
105
+ stripeBg: "transparent",
106
+ },
107
+ ]));
108
+ let tableStylesInjected = false;
109
+ function injectTableStyles() {
110
+ if (tableStylesInjected || typeof document === "undefined")
111
+ return;
112
+ tableStylesInjected = true;
113
+ const rules = [
114
+ `
115
+ [data-fynix-dt] {
116
+ width: 100%;
117
+ border-collapse: collapse;
118
+ font-size: 14px;
119
+ font-family: inherit;
120
+ }
121
+ [data-fynix-dt] th,
122
+ [data-fynix-dt] td {
123
+ padding: 8px 12px;
124
+ text-align: left;
125
+ vertical-align: middle;
126
+ border-bottom: 1px solid;
127
+ white-space: nowrap;
128
+ }
129
+ [data-fynix-dt] th {
130
+ font-weight: 500;
131
+ font-size: 12px;
132
+ }
133
+ [data-fynix-dt] tr:last-child td {
134
+ border-bottom: none;
135
+ }
136
+ [data-fynix-dt-actions] {
137
+ display: flex;
138
+ gap: 6px;
139
+ align-items: center;
140
+ }
141
+ [data-fynix-dt-btn] {
142
+ display: inline-block;
143
+ cursor: pointer;
144
+ font-size: 12px;
145
+ font-weight: 400;
146
+ padding: 3px 9px;
147
+ border-radius: 4px;
148
+ border: 1px solid;
149
+ line-height: 1.5;
150
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
151
+ user-select: none;
152
+ text-decoration: none;
153
+ white-space: nowrap;
154
+ }
155
+ `,
156
+ ];
157
+ for (const [variant, theme] of Object.entries(VARIANT_THEMES)) {
158
+ rules.push(`
159
+ [data-fynix-dt="${variant}"] th {
160
+ background-color: ${theme.headerBg} !important;
161
+ color: ${theme.headerColor} !important;
162
+ border-color: ${theme.headerBorder} !important;
163
+ }
164
+ [data-fynix-dt="${variant}"] td {
165
+ border-color: ${theme.rowBorder} !important;
166
+ }
167
+ [data-fynix-dt="${variant}"][data-fynix-dt-hover] tr:hover td {
168
+ background-color: ${theme.rowHoverBg} !important;
169
+ }
170
+ [data-fynix-dt="${variant}"][data-fynix-dt-stripe] tr:nth-child(even) td {
171
+ background-color: ${theme.stripeBg} !important;
172
+ }
173
+
174
+ /* View button (filled with accent) */
175
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="view"] {
176
+ background-color: ${theme.accentBg};
177
+ color: ${theme.accentColor};
178
+ border-color: ${theme.accentBorder};
179
+ }
180
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="view"]:hover {
181
+ background-color: ${theme.accentHoverBg} !important;
182
+ }
183
+
184
+ /* Edit button (outline accent) */
185
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="edit"] {
186
+ background-color: transparent;
187
+ color: ${theme.accentBg === "transparent" ? theme.headerColor : theme.accentBg};
188
+ border-color: ${theme.accentBorder};
189
+ }
190
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="edit"]:hover {
191
+ background-color: ${theme.accentBg} !important;
192
+ color: ${theme.accentColor} !important;
193
+ }
194
+
195
+ /* Delete button (always danger outline regardless of variant) */
196
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="delete"] {
197
+ background-color: transparent;
198
+ color: #dc3545;
199
+ border-color: #dc3545;
200
+ }
201
+ [data-fynix-dt="${variant}"] [data-fynix-dt-btn="delete"]:hover {
202
+ background-color: #dc3545 !important;
203
+ color: #fff !important;
204
+ }
205
+ `);
206
+ const outlineTheme = OUTLINE_THEMES[variant];
207
+ rules.push(`
208
+ [data-fynix-dt="outline-${variant}"] th {
209
+ background-color: ${outlineTheme.headerBg} !important;
210
+ color: ${theme.headerColor} !important;
211
+ border-color: ${theme.accentBorder} !important;
212
+ }
213
+ [data-fynix-dt="outline-${variant}"] td {
214
+ border-color: ${theme.rowBorder} !important;
215
+ }
216
+ [data-fynix-dt="outline-${variant}"][data-fynix-dt-hover] tr:hover td {
217
+ background-color: ${theme.rowHoverBg} !important;
218
+ }
219
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="view"] {
220
+ background-color: transparent;
221
+ color: ${theme.accentBg};
222
+ border-color: ${theme.accentBorder};
223
+ }
224
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="view"]:hover {
225
+ background-color: ${theme.accentBg} !important;
226
+ color: ${theme.accentColor} !important;
227
+ }
228
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="edit"] {
229
+ background-color: transparent;
230
+ color: #198754;
231
+ border-color: #198754;
232
+ }
233
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="edit"]:hover {
234
+ background-color: #198754 !important;
235
+ color: #fff !important;
236
+ }
237
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="delete"] {
238
+ background-color: transparent;
239
+ color: #dc3545;
240
+ border-color: #dc3545;
241
+ }
242
+ [data-fynix-dt="outline-${variant}"] [data-fynix-dt-btn="delete"]:hover {
243
+ background-color: #dc3545 !important;
244
+ color: #fff !important;
245
+ }
246
+ `);
247
+ }
248
+ const style = document.createElement("style");
249
+ style.setAttribute("data-fynix", "datatable-styles");
250
+ style.textContent = rules.join("\n");
251
+ document.head.appendChild(style);
252
+ }
253
+ function getCellValue(row, key) {
254
+ return row[key];
255
+ }
256
+ export function DataTable({ columns, data, actions, style: wrapStyle = {}, class: wrapClass = "", tableStyle = {}, tableClass = "", rc, ...rest }) {
257
+ const thead = Fynix("thead", {}, Fynix("tr", {}, ...columns.map((col) => Fynix("th", { style: col.style ?? {}, class: col.class ?? "" }, col.label)), actions ? Fynix("th", {}, "Actions") : null));
258
+ const tbody = Fynix("tbody", {}, ...data.map((row, rowIndex) => Fynix("tr", {}, ...columns.map((col) => {
259
+ const raw = getCellValue(row, col.key);
260
+ const cell = col.render ? col.render(raw, row, rowIndex) : raw;
261
+ return Fynix("td", { style: col.style ?? {}, class: col.class ?? "" }, cell);
262
+ }), actions
263
+ ? Fynix("td", {}, Fynix("div", { style: { display: "flex", gap: "6px" } }, actions.view !== false && actions.view
264
+ ? Fynix("button", {
265
+ type: "button",
266
+ "r-click": () => actions.view(row, rowIndex),
267
+ }, "View")
268
+ : null, actions.edit !== false && actions.edit
269
+ ? Fynix("button", {
270
+ type: "button",
271
+ "r-click": () => actions.edit(row, rowIndex),
272
+ }, "Edit")
273
+ : null, actions.delete !== false && actions.delete
274
+ ? Fynix("button", {
275
+ type: "button",
276
+ "r-click": () => actions.delete(row, rowIndex),
277
+ }, "Delete")
278
+ : null, ...(actions.extra ?? []).map((extra) => Fynix("button", {
279
+ type: "button",
280
+ style: extra.style ?? {},
281
+ class: extra.class ?? "",
282
+ "r-click": () => extra.handler(row, rowIndex),
283
+ }, extra.label))))
284
+ : null)));
285
+ return Fynix("div", { style: wrapStyle, class: wrapClass, rc }, Fynix("table", { style: tableStyle, class: tableClass, ...rest }, thead, tbody));
286
+ }
287
+ function UIDataTable({ columns, data, actions, variant = "primary", outline = false, striped = false, hoverable = true, bordered = true, style: wrapStyle = {}, class: wrapClass = "", tableStyle = {}, tableClass = "", rc, }) {
288
+ injectTableStyles();
289
+ const dataAttr = outline ? `outline-${variant}` : variant;
290
+ const tableAttrs = {
291
+ "data-fynix-dt": dataAttr,
292
+ ...(hoverable ? { "data-fynix-dt-hover": "" } : {}),
293
+ ...(striped ? { "data-fynix-dt-stripe": "" } : {}),
294
+ style: tableStyle,
295
+ class: tableClass,
296
+ };
297
+ const borderStyle = bordered
298
+ ? {
299
+ border: "1px solid",
300
+ borderColor: "rgba(0,0,0,0.08)",
301
+ borderRadius: "6px",
302
+ overflow: "hidden",
303
+ }
304
+ : {};
305
+ const wrapAttrs = {
306
+ style: { display: "block", ...borderStyle, ...wrapStyle },
307
+ class: wrapClass,
308
+ rc,
309
+ };
310
+ const thead = Fynix("thead", {}, Fynix("tr", {}, ...columns.map((col) => Fynix("th", { style: col.style ?? {}, class: col.class ?? "" }, col.label)), actions ? Fynix("th", {}, "Actions") : null));
311
+ const tbody = Fynix("tbody", {}, ...data.map((row, rowIndex) => Fynix("tr", {}, ...columns.map((col) => {
312
+ const raw = getCellValue(row, col.key);
313
+ const cell = col.render ? col.render(raw, row, rowIndex) : raw;
314
+ return Fynix("td", { style: col.style ?? {}, class: col.class ?? "" }, cell);
315
+ }), actions
316
+ ? Fynix("td", {}, Fynix("div", { "data-fynix-dt-actions": "" }, actions.view !== false && actions.view
317
+ ? Fynix("button", {
318
+ type: "button",
319
+ "data-fynix-dt-btn": "view",
320
+ "r-click": () => actions.view(row, rowIndex),
321
+ }, "View")
322
+ : null, actions.edit !== false && actions.edit
323
+ ? Fynix("button", {
324
+ type: "button",
325
+ "data-fynix-dt-btn": "edit",
326
+ "r-click": () => actions.edit(row, rowIndex),
327
+ }, "Edit")
328
+ : null, actions.delete !== false && actions.delete
329
+ ? Fynix("button", {
330
+ type: "button",
331
+ "data-fynix-dt-btn": "delete",
332
+ "r-click": () => actions.delete(row, rowIndex),
333
+ }, "Delete")
334
+ : null, ...(actions.extra ?? []).map((extra) => Fynix("button", {
335
+ type: "button",
336
+ "data-fynix-dt-btn": "extra",
337
+ style: extra.style ?? {},
338
+ class: extra.class ?? "",
339
+ "r-click": () => extra.handler(row, rowIndex),
340
+ }, extra.label))))
341
+ : null)));
342
+ return Fynix("div", wrapAttrs, Fynix("table", tableAttrs, thead, tbody));
343
+ }
344
+ export const PrimaryDataTable = (p) => UIDataTable({ ...p, variant: "primary" });
345
+ export const SecondaryDataTable = (p) => UIDataTable({ ...p, variant: "secondary" });
346
+ export const SuccessDataTable = (p) => UIDataTable({ ...p, variant: "success" });
347
+ export const DangerDataTable = (p) => UIDataTable({ ...p, variant: "danger" });
348
+ export const WarningDataTable = (p) => UIDataTable({ ...p, variant: "warning" });
349
+ export const InfoDataTable = (p) => UIDataTable({ ...p, variant: "info" });
350
+ export const LightDataTable = (p) => UIDataTable({ ...p, variant: "light" });
351
+ export const DarkDataTable = (p) => UIDataTable({ ...p, variant: "dark" });
352
+ export const OutlinePrimaryDataTable = (p) => UIDataTable({ ...p, variant: "primary", outline: true });
353
+ export const OutlineSecondaryDataTable = (p) => UIDataTable({ ...p, variant: "secondary", outline: true });
354
+ export const OutlineSuccessDataTable = (p) => UIDataTable({ ...p, variant: "success", outline: true });
355
+ export const OutlineDangerDataTable = (p) => UIDataTable({ ...p, variant: "danger", outline: true });
356
+ export const OutlineWarningDataTable = (p) => UIDataTable({ ...p, variant: "warning", outline: true });
357
+ export const OutlineInfoDataTable = (p) => UIDataTable({ ...p, variant: "info", outline: true });
358
+ export const OutlineLightDataTable = (p) => UIDataTable({ ...p, variant: "light", outline: true });
359
+ export const OutlineDarkDataTable = (p) => UIDataTable({ ...p, variant: "dark", outline: true });
@@ -173,22 +173,22 @@ function injectButtonStyles() {
173
173
  stylesInjected = true;
174
174
  const rules = [];
175
175
  for (const [variant, colors] of Object.entries(VARIANT_STYLES)) {
176
- rules.push(`
177
- button[data-fynix-btn="${variant}"]:not([disabled]):hover {
178
- background-color: ${colors.hoverBg} !important;
179
- color: ${colors.hoverColor} !important;
180
- border-color: ${colors.hoverBorder} !important;
181
- ${variant === "link" ? "text-decoration: underline !important;" : ""}
182
- }
176
+ rules.push(`
177
+ button[data-fynix-btn="${variant}"]:not([disabled]):hover {
178
+ background-color: ${colors.hoverBg} !important;
179
+ color: ${colors.hoverColor} !important;
180
+ border-color: ${colors.hoverBorder} !important;
181
+ ${variant === "link" ? "text-decoration: underline !important;" : ""}
182
+ }
183
183
  `);
184
184
  }
185
185
  for (const [variant, colors] of Object.entries(OUTLINE_STYLES)) {
186
- rules.push(`
187
- button[data-fynix-btn="outline-${variant}"]:not([disabled]):hover {
188
- background-color: ${colors.hoverBg} !important;
189
- color: ${colors.hoverColor} !important;
190
- border-color: ${colors.hoverBorder} !important;
191
- }
186
+ rules.push(`
187
+ button[data-fynix-btn="outline-${variant}"]:not([disabled]):hover {
188
+ background-color: ${colors.hoverBg} !important;
189
+ color: ${colors.hoverColor} !important;
190
+ border-color: ${colors.hoverBorder} !important;
191
+ }
192
192
  `);
193
193
  }
194
194
  const style = document.createElement("style");
@@ -1,2 +1,3 @@
1
1
  export { Button, PrimaryButton, SecondaryButton, SuccessButton, DangerButton, WarningButton, InfoButton, LightButton, DarkButton, LinkButton, } from "./button";
2
+ export { DataTable, PrimaryDataTable, SecondaryDataTable, SuccessDataTable, DangerDataTable, WarningDataTable, InfoDataTable, LightDataTable, DarkDataTable, OutlinePrimaryDataTable, OutlineSecondaryDataTable, OutlineSuccessDataTable, OutlineDangerDataTable, OutlineWarningDataTable, OutlineInfoDataTable, OutlineLightDataTable, OutlineDarkDataTable, } from "./DataTable";
2
3
  export { Path } from "./path";
@@ -1,22 +1,19 @@
1
1
  import { Fragment } from "../runtime.js";
2
2
  export function For(props) {
3
- let items = [];
4
- if (props.each &&
5
- typeof props.each === "object" &&
6
- "_isNixState" in props.each) {
7
- items = props.each.value;
8
- }
9
- else if (Array.isArray(props.each)) {
10
- items = props.each;
11
- }
3
+ const isReactive = props.each && typeof props.each === "object" && "_isNixState" in props.each;
4
+ const items = isReactive
5
+ ? props.each.value
6
+ : Array.isArray(props.each)
7
+ ? props.each
8
+ : [];
12
9
  let renderer;
13
10
  if (typeof props.children === "function") {
14
11
  renderer = props.children;
15
12
  }
16
13
  else if (Array.isArray(props.children)) {
17
- const firstChild = props.children[0];
18
- if (typeof firstChild === "function") {
19
- renderer = firstChild;
14
+ const first = props.children[0];
15
+ if (typeof first === "function") {
16
+ renderer = first;
20
17
  }
21
18
  }
22
19
  if (!renderer) {
@@ -25,18 +22,17 @@ export function For(props) {
25
22
  }
26
23
  return { type: Fragment, props: { children: [] }, key: null };
27
24
  }
25
+ const finalRenderer = renderer;
28
26
  const mapped = items.map((item, index) => {
29
27
  try {
30
- return renderer(item, index);
28
+ const vnode = finalRenderer(item, index);
29
+ return { ...vnode, key: vnode.key ?? index };
31
30
  }
32
31
  catch (error) {
33
32
  console.error(`[Fynix] Error rendering item at index ${index}:`, error);
34
33
  return {
35
34
  type: "div",
36
- props: {
37
- children: ["Error rendering item"],
38
- style: "color: red;",
39
- },
35
+ props: { children: ["Error rendering item"], style: "color: red;" },
40
36
  key: index,
41
37
  };
42
38
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fynixui",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "type": "module",
5
5
  "description": "Core package for Fynix UI framework - A lightweight, reactive UI framework with TypeScript support.",
6
6
  "main": "./dist/fynix/index.js",
package/dist/runtime.js CHANGED
@@ -758,9 +758,7 @@ function endComponent() {
758
758
  ctx.rerender = createRerender(ctx);
759
759
  const unsub = state.subscribe(() => {
760
760
  if (ctx.rerender && ctx._isMounted) {
761
- typeof queueMicrotask === "function"
762
- ? queueMicrotask(() => ctx.rerender())
763
- : setTimeout(ctx.rerender, 0);
761
+ ctx.rerender();
764
762
  }
765
763
  });
766
764
  ctx._subscriptions.add(state);
@@ -782,7 +780,7 @@ function createRerender(ctx) {
782
780
  if (ctx._isRerendering || !ctx._isMounted)
783
781
  return;
784
782
  if (ctx._fiber) {
785
- fiberReconciler.scheduleUpdate(ctx._fiber, "normal");
783
+ fiberReconciler.scheduleUpdate(ctx._fiber, "high");
786
784
  }
787
785
  else if (ctx._vnode) {
788
786
  console.warn("[Fynix] Rerender triggered before fiber assigned — skipping.");
@@ -875,6 +873,7 @@ function removeDomCleanups(node) {
875
873
  class FiberReconciler {
876
874
  constructor() {
877
875
  this.wipRoot = null;
876
+ this.wipEntry = null;
878
877
  this.nextWork = null;
879
878
  this.deletions = [];
880
879
  }
@@ -882,6 +881,7 @@ class FiberReconciler {
882
881
  const rootFiber = this.vnodeToFiber(vnode, null, null);
883
882
  rootFiber._domNode = container;
884
883
  this.wipRoot = rootFiber;
884
+ this.wipEntry = null;
885
885
  this.nextWork = rootFiber;
886
886
  this.deletions = [];
887
887
  this.scheduleRender("high");
@@ -893,6 +893,7 @@ class FiberReconciler {
893
893
  while (root.parent)
894
894
  root = root.parent;
895
895
  this.wipRoot = root;
896
+ this.wipEntry = wip;
896
897
  this.nextWork = wip;
897
898
  this.deletions = [];
898
899
  this.scheduleRender(priority);
@@ -959,6 +960,14 @@ class FiberReconciler {
959
960
  updateComponentFiber(fiber) {
960
961
  const vnode = fiber._vnode;
961
962
  let ctx = componentInstances.get(vnode);
963
+ if (!ctx && fiber.alternate?._vnode) {
964
+ ctx = componentInstances.get(fiber.alternate._vnode);
965
+ if (ctx) {
966
+ componentInstances.delete(fiber.alternate._vnode);
967
+ componentInstances.set(vnode, ctx);
968
+ ctx._vnode = vnode;
969
+ }
970
+ }
962
971
  if (!ctx) {
963
972
  ctx = makeContext(vnode, fiber.type);
964
973
  componentInstances.set(vnode, ctx);
@@ -1004,9 +1013,7 @@ class FiberReconciler {
1004
1013
  ctx.rerender = createRerender(ctx);
1005
1014
  const unsub = state.subscribe(() => {
1006
1015
  if (ctx.rerender && ctx._isMounted) {
1007
- typeof queueMicrotask === "function"
1008
- ? queueMicrotask(() => ctx.rerender())
1009
- : setTimeout(ctx.rerender, 0);
1016
+ ctx.rerender();
1010
1017
  }
1011
1018
  });
1012
1019
  ctx._subscriptions.add(state);
@@ -1105,10 +1112,10 @@ class FiberReconciler {
1105
1112
  newFiber.props = el.props;
1106
1113
  newFiber.key = el.key;
1107
1114
  newFiber.alternate = matchFiber;
1108
- newFiber.effectTag = "UPDATE";
1109
1115
  newFiber.parent = wipFiber;
1110
1116
  newFiber._vnode = el;
1111
1117
  el._fiber = newFiber;
1118
+ newFiber.effectTag = typeof el.type === "function" ? null : "UPDATE";
1112
1119
  }
1113
1120
  else {
1114
1121
  if (matchFiber) {
@@ -1139,9 +1146,14 @@ class FiberReconciler {
1139
1146
  return;
1140
1147
  this.deletions.forEach((f) => this.commitDeletion(f));
1141
1148
  this.deletions = [];
1142
- if (this.wipRoot.child)
1149
+ if (this.wipEntry) {
1150
+ this.commitWork(this.wipEntry);
1151
+ }
1152
+ else if (this.wipRoot.child) {
1143
1153
  this.commitWork(this.wipRoot.child);
1154
+ }
1144
1155
  this.wipRoot = null;
1156
+ this.wipEntry = null;
1145
1157
  this.nextWork = null;
1146
1158
  }
1147
1159
  commitWork(fiber) {
@@ -0,0 +1,54 @@
1
+ type TableVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
2
+ type ActionHandler<T = any> = (row: T, index: number) => void;
3
+ export interface ColumnDef<T = any> {
4
+ key: keyof T | string;
5
+ label: string;
6
+ style?: Record<string, string>;
7
+ class?: string;
8
+ render?: (value: any, row: T, index: number) => any;
9
+ }
10
+ export interface ActionsDef<T = any> {
11
+ view?: ActionHandler<T> | false;
12
+ edit?: ActionHandler<T> | false;
13
+ delete?: ActionHandler<T> | false;
14
+ extra?: Array<{
15
+ label: string;
16
+ handler: ActionHandler<T>;
17
+ style?: Record<string, string>;
18
+ class?: string;
19
+ }>;
20
+ }
21
+ export interface DataTableProps<T = any> {
22
+ columns: ColumnDef<T>[];
23
+ data: T[];
24
+ actions?: ActionsDef<T>;
25
+ variant?: TableVariant;
26
+ outline?: boolean;
27
+ striped?: boolean;
28
+ hoverable?: boolean;
29
+ bordered?: boolean;
30
+ style?: Record<string, string>;
31
+ class?: string;
32
+ tableStyle?: Record<string, string>;
33
+ tableClass?: string;
34
+ rc?: string;
35
+ [key: string]: any;
36
+ }
37
+ export declare function DataTable<T = any>({ columns, data, actions, style: wrapStyle, class: wrapClass, tableStyle, tableClass, rc, ...rest }: DataTableProps<T>): any;
38
+ export declare const PrimaryDataTable: <T>(p: DataTableProps<T>) => any;
39
+ export declare const SecondaryDataTable: <T>(p: DataTableProps<T>) => any;
40
+ export declare const SuccessDataTable: <T>(p: DataTableProps<T>) => any;
41
+ export declare const DangerDataTable: <T>(p: DataTableProps<T>) => any;
42
+ export declare const WarningDataTable: <T>(p: DataTableProps<T>) => any;
43
+ export declare const InfoDataTable: <T>(p: DataTableProps<T>) => any;
44
+ export declare const LightDataTable: <T>(p: DataTableProps<T>) => any;
45
+ export declare const DarkDataTable: <T>(p: DataTableProps<T>) => any;
46
+ export declare const OutlinePrimaryDataTable: <T>(p: DataTableProps<T>) => any;
47
+ export declare const OutlineSecondaryDataTable: <T>(p: DataTableProps<T>) => any;
48
+ export declare const OutlineSuccessDataTable: <T>(p: DataTableProps<T>) => any;
49
+ export declare const OutlineDangerDataTable: <T>(p: DataTableProps<T>) => any;
50
+ export declare const OutlineWarningDataTable: <T>(p: DataTableProps<T>) => any;
51
+ export declare const OutlineInfoDataTable: <T>(p: DataTableProps<T>) => any;
52
+ export declare const OutlineLightDataTable: <T>(p: DataTableProps<T>) => any;
53
+ export declare const OutlineDarkDataTable: <T>(p: DataTableProps<T>) => any;
54
+ export {};
@@ -1,2 +1,3 @@
1
1
  export { Button, PrimaryButton, SecondaryButton, SuccessButton, DangerButton, WarningButton, InfoButton, LightButton, DarkButton, LinkButton, } from "./button";
2
+ export { DataTable, PrimaryDataTable, SecondaryDataTable, SuccessDataTable, DangerDataTable, WarningDataTable, InfoDataTable, LightDataTable, DarkDataTable, OutlinePrimaryDataTable, OutlineSecondaryDataTable, OutlineSuccessDataTable, OutlineDangerDataTable, OutlineWarningDataTable, OutlineInfoDataTable, OutlineLightDataTable, OutlineDarkDataTable, } from "./DataTable";
2
3
  export { Path } from "./path";
@@ -2,7 +2,7 @@ import { VNode } from "../types/fnx";
2
2
  interface ReactiveState<T> {
3
3
  value: T;
4
4
  _isNixState: boolean;
5
- subscribe(callback: (value: T) => void): () => void;
5
+ subscribe(callback: () => void): () => void;
6
6
  }
7
7
  interface ForProps<T> {
8
8
  each: T[] | ReactiveState<T[]>;
@@ -130,6 +130,7 @@ export declare namespace h {
130
130
  export declare const Fynix: typeof h;
131
131
  declare class FiberReconciler {
132
132
  private wipRoot;
133
+ private wipEntry;
133
134
  private nextWork;
134
135
  private deletions;
135
136
  mountRoot(vnode: VNode, container: Element): void;