@mappoh/nova 0.1.16 → 0.2.1

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 (120) hide show
  1. package/README.md +46 -0
  2. package/dist/accordion/accordion.d.ts +39 -0
  3. package/dist/accordion/accordion.d.ts.map +1 -0
  4. package/dist/accordion/accordion.js +203 -0
  5. package/dist/accordion/accordion.js.map +1 -0
  6. package/dist/accordion/index.d.ts +3 -0
  7. package/dist/accordion/index.d.ts.map +1 -0
  8. package/dist/accordion/index.js +2 -0
  9. package/dist/accordion/index.js.map +1 -0
  10. package/dist/breadcrumb/breadcrumb.d.ts +37 -0
  11. package/dist/breadcrumb/breadcrumb.d.ts.map +1 -0
  12. package/dist/breadcrumb/breadcrumb.js +139 -0
  13. package/dist/breadcrumb/breadcrumb.js.map +1 -0
  14. package/dist/breadcrumb/index.d.ts +3 -0
  15. package/dist/breadcrumb/index.d.ts.map +1 -0
  16. package/dist/breadcrumb/index.js +2 -0
  17. package/dist/breadcrumb/index.js.map +1 -0
  18. package/dist/canvas/noise-wasm.d.ts +30 -0
  19. package/dist/canvas/noise-wasm.d.ts.map +1 -0
  20. package/dist/canvas/noise-wasm.js +82 -0
  21. package/dist/canvas/noise-wasm.js.map +1 -0
  22. package/dist/canvas/physics-wasm.d.ts +48 -0
  23. package/dist/canvas/physics-wasm.d.ts.map +1 -0
  24. package/dist/canvas/physics-wasm.js +66 -0
  25. package/dist/canvas/physics-wasm.js.map +1 -0
  26. package/dist/carousel/carousel.d.ts +51 -0
  27. package/dist/carousel/carousel.d.ts.map +1 -0
  28. package/dist/carousel/carousel.js +236 -0
  29. package/dist/carousel/carousel.js.map +1 -0
  30. package/dist/carousel/index.d.ts +3 -0
  31. package/dist/carousel/index.d.ts.map +1 -0
  32. package/dist/carousel/index.js +2 -0
  33. package/dist/carousel/index.js.map +1 -0
  34. package/dist/clipboard/clipboard.d.ts +15 -0
  35. package/dist/clipboard/clipboard.d.ts.map +1 -0
  36. package/dist/clipboard/clipboard.js +76 -0
  37. package/dist/clipboard/clipboard.js.map +1 -0
  38. package/dist/clipboard/index.d.ts +2 -0
  39. package/dist/clipboard/index.d.ts.map +1 -0
  40. package/dist/clipboard/index.js +2 -0
  41. package/dist/clipboard/index.js.map +1 -0
  42. package/dist/component/diff-wasm.d.ts +35 -0
  43. package/dist/component/diff-wasm.d.ts.map +1 -0
  44. package/dist/component/diff-wasm.js +52 -0
  45. package/dist/component/diff-wasm.js.map +1 -0
  46. package/dist/component/template.d.ts.map +1 -1
  47. package/dist/component/template.js +16 -5
  48. package/dist/component/template.js.map +1 -1
  49. package/dist/forms/wasm-validators.d.ts +60 -0
  50. package/dist/forms/wasm-validators.d.ts.map +1 -0
  51. package/dist/forms/wasm-validators.js +121 -0
  52. package/dist/forms/wasm-validators.js.map +1 -0
  53. package/dist/image/wasm.d.ts +47 -0
  54. package/dist/image/wasm.d.ts.map +1 -0
  55. package/dist/image/wasm.js +133 -0
  56. package/dist/image/wasm.js.map +1 -0
  57. package/dist/infinite-scroll/index.d.ts +3 -0
  58. package/dist/infinite-scroll/index.d.ts.map +1 -0
  59. package/dist/infinite-scroll/index.js +2 -0
  60. package/dist/infinite-scroll/index.js.map +1 -0
  61. package/dist/infinite-scroll/infinite-scroll.d.ts +33 -0
  62. package/dist/infinite-scroll/infinite-scroll.d.ts.map +1 -0
  63. package/dist/infinite-scroll/infinite-scroll.js +94 -0
  64. package/dist/infinite-scroll/infinite-scroll.js.map +1 -0
  65. package/dist/markdown/index.d.ts +2 -0
  66. package/dist/markdown/index.d.ts.map +1 -0
  67. package/dist/markdown/index.js +2 -0
  68. package/dist/markdown/index.js.map +1 -0
  69. package/dist/markdown/markdown.d.ts +14 -0
  70. package/dist/markdown/markdown.d.ts.map +1 -0
  71. package/dist/markdown/markdown.js +194 -0
  72. package/dist/markdown/markdown.js.map +1 -0
  73. package/dist/markdown/wasm.d.ts +11 -0
  74. package/dist/markdown/wasm.d.ts.map +1 -0
  75. package/dist/markdown/wasm.js +28 -0
  76. package/dist/markdown/wasm.js.map +1 -0
  77. package/dist/modal/modal.d.ts.map +1 -1
  78. package/dist/modal/modal.js +11 -1
  79. package/dist/modal/modal.js.map +1 -1
  80. package/dist/popover/index.d.ts +3 -0
  81. package/dist/popover/index.d.ts.map +1 -0
  82. package/dist/popover/index.js +2 -0
  83. package/dist/popover/index.js.map +1 -0
  84. package/dist/popover/popover.d.ts +56 -0
  85. package/dist/popover/popover.d.ts.map +1 -0
  86. package/dist/popover/popover.js +242 -0
  87. package/dist/popover/popover.js.map +1 -0
  88. package/dist/progress/index.d.ts +3 -0
  89. package/dist/progress/index.d.ts.map +1 -0
  90. package/dist/progress/index.js +2 -0
  91. package/dist/progress/index.js.map +1 -0
  92. package/dist/progress/progress.d.ts +39 -0
  93. package/dist/progress/progress.d.ts.map +1 -0
  94. package/dist/progress/progress.js +172 -0
  95. package/dist/progress/progress.js.map +1 -0
  96. package/dist/search/wasm.d.ts +2 -2
  97. package/dist/search/wasm.d.ts.map +1 -1
  98. package/dist/search/wasm.js +2 -3
  99. package/dist/search/wasm.js.map +1 -1
  100. package/dist/security/wasm-crypto.d.ts +53 -0
  101. package/dist/security/wasm-crypto.d.ts.map +1 -0
  102. package/dist/security/wasm-crypto.js +84 -0
  103. package/dist/security/wasm-crypto.js.map +1 -0
  104. package/dist/stepper/index.d.ts +3 -0
  105. package/dist/stepper/index.d.ts.map +1 -0
  106. package/dist/stepper/index.js +2 -0
  107. package/dist/stepper/index.js.map +1 -0
  108. package/dist/stepper/stepper.d.ts +49 -0
  109. package/dist/stepper/stepper.d.ts.map +1 -0
  110. package/dist/stepper/stepper.js +173 -0
  111. package/dist/stepper/stepper.js.map +1 -0
  112. package/dist/virtual-list/index.d.ts +3 -0
  113. package/dist/virtual-list/index.d.ts.map +1 -0
  114. package/dist/virtual-list/index.js +2 -0
  115. package/dist/virtual-list/index.js.map +1 -0
  116. package/dist/virtual-list/virtual-list.d.ts +37 -0
  117. package/dist/virtual-list/virtual-list.d.ts.map +1 -0
  118. package/dist/virtual-list/virtual-list.js +190 -0
  119. package/dist/virtual-list/virtual-list.js.map +1 -0
  120. package/package.json +80 -2
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Nova Engine — Crypto WASM Accelerator
3
+ *
4
+ * Optional WASM-accelerated password hashing compiled from Rust.
5
+ * Provides Argon2id, bcrypt, and PBKDF2-SHA256 implementations
6
+ * that run entirely in WASM (no Web Crypto dependency).
7
+ */
8
+ let wasm = null;
9
+ let initPromise = null;
10
+ /**
11
+ * Initialize the WASM crypto module.
12
+ * Call once at app startup. Safe to call multiple times.
13
+ */
14
+ export async function initWasm() {
15
+ if (wasm)
16
+ return;
17
+ if (initPromise)
18
+ return initPromise;
19
+ initPromise = (async () => {
20
+ // @ts-ignore — wasm-bindgen generated glue
21
+ const mod = await import('./wasm/crypto/nova_crypto_wasm.js');
22
+ wasm = mod;
23
+ })();
24
+ return initPromise;
25
+ }
26
+ /** Check if the WASM crypto module is loaded. */
27
+ export function isReady() {
28
+ return wasm !== null;
29
+ }
30
+ /**
31
+ * Hash a password using Argon2id (WASM-accelerated).
32
+ * Returns an encoded hash string, or null if WASM not loaded.
33
+ */
34
+ export function argon2Hash(password, salt, options = {}) {
35
+ if (!wasm)
36
+ return null;
37
+ return wasm.argon2Hash(password, salt, options.timeCost ?? 3, options.memoryCost ?? 19456, options.hashLength ?? 32);
38
+ }
39
+ /**
40
+ * Verify a password against an Argon2id hash (WASM-accelerated).
41
+ * Returns null if WASM not loaded.
42
+ */
43
+ export function argon2Verify(password, hash) {
44
+ if (!wasm)
45
+ return null;
46
+ return wasm.argon2Verify(password, hash);
47
+ }
48
+ /**
49
+ * Hash a password using bcrypt (WASM-accelerated).
50
+ * Returns an encoded hash string, or null if WASM not loaded.
51
+ */
52
+ export function bcryptHash(password, cost = 10) {
53
+ if (!wasm)
54
+ return null;
55
+ return wasm.bcryptHash(password, cost);
56
+ }
57
+ /**
58
+ * Verify a password against a bcrypt hash (WASM-accelerated).
59
+ * Returns null if WASM not loaded.
60
+ */
61
+ export function bcryptVerify(password, hash) {
62
+ if (!wasm)
63
+ return null;
64
+ return wasm.bcryptVerify(password, hash);
65
+ }
66
+ /**
67
+ * Derive a key using PBKDF2-SHA256 (WASM-accelerated).
68
+ * Returns the derived key bytes, or null if WASM not loaded.
69
+ */
70
+ export function pbkdf2(password, salt, iterations = 600_000, keyLength = 32) {
71
+ if (!wasm)
72
+ return null;
73
+ return wasm.pbkdf2(password, salt, iterations, keyLength);
74
+ }
75
+ /**
76
+ * Constant-time byte comparison (WASM-accelerated).
77
+ * Returns null if WASM not loaded.
78
+ */
79
+ export function constantTimeEqual(a, b) {
80
+ if (!wasm)
81
+ return null;
82
+ return wasm.constantTimeEq(a, b);
83
+ }
84
+ //# sourceMappingURL=wasm-crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm-crypto.js","sourceRoot":"","sources":["../../src/security/wasm-crypto.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoBH,IAAI,IAAI,GAAuB,IAAI,CAAC;AACpC,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,IAAI;QAAE,OAAO;IACjB,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QACxB,2CAA2C;QAC3C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;QAC9D,IAAI,GAAG,GAA6B,CAAC;IACvC,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,KAAK,IAAI,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,QAAgB,EAChB,IAAgB,EAChB,UAAyB,EAAE;IAE3B,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,UAAU,CACpB,QAAQ,EACR,IAAI,EACJ,OAAO,CAAC,QAAQ,IAAI,CAAC,EACrB,OAAO,CAAC,UAAU,IAAI,KAAK,EAC3B,OAAO,CAAC,UAAU,IAAI,EAAE,CACzB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,IAAY;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,IAAI,GAAG,EAAE;IACpD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,IAAY;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CACpB,QAAgB,EAChB,IAAgB,EAChB,UAAU,GAAG,OAAO,EACpB,SAAS,GAAG,EAAE;IAEd,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAa,EAAE,CAAa;IAC5D,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createStepper } from './stepper';
2
+ export type { StepperOptions, StepperInstance, StepDefinition } from './stepper';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stepper/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createStepper } from './stepper';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stepper/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Nova Engine — Stepper
3
+ *
4
+ * Multi-step progress indicator with validation,
5
+ * horizontal/vertical layout, and ARIA attributes.
6
+ */
7
+ export interface StepDefinition {
8
+ /** Display label */
9
+ label: string;
10
+ /** Optional description text */
11
+ description?: string;
12
+ /** Optional icon HTML */
13
+ icon?: string;
14
+ /** Validate before advancing past this step. Return false to block. */
15
+ validate?: () => boolean | Promise<boolean>;
16
+ }
17
+ export interface StepperOptions {
18
+ /** Container element to render into */
19
+ container: HTMLElement;
20
+ /** Step definitions */
21
+ steps: StepDefinition[];
22
+ /** Layout direction. Default: 'horizontal' */
23
+ orientation?: 'horizontal' | 'vertical';
24
+ /** Initial active step. Default: 0 */
25
+ defaultStep?: number;
26
+ /** Must complete steps in order. Default: true */
27
+ linear?: boolean;
28
+ /** Callback when the active step changes */
29
+ onChange?: (step: number) => void;
30
+ }
31
+ export interface StepperInstance {
32
+ /** Advance to the next step. Returns false if validation fails. */
33
+ next(): Promise<boolean>;
34
+ /** Go to the previous step. */
35
+ prev(): void;
36
+ /** Jump to a specific step. Returns false if validation fails or blocked by linear mode. */
37
+ goTo(index: number): Promise<boolean>;
38
+ /** Current step index */
39
+ readonly currentStep: number;
40
+ /** Total number of steps */
41
+ readonly stepCount: number;
42
+ /** Manually set a step's visual state */
43
+ setStepState(index: number, state: 'active' | 'completed' | 'error'): void;
44
+ /** Clean up and remove rendered UI */
45
+ destroy(): void;
46
+ }
47
+ /** Create a multi-step progress indicator. */
48
+ export declare function createStepper(options: StepperOptions): StepperInstance;
49
+ //# sourceMappingURL=stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepper.d.ts","sourceRoot":"","sources":["../../src/stepper/stepper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,SAAS,EAAE,WAAW,CAAC;IACvB,uBAAuB;IACvB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,+BAA+B;IAC/B,IAAI,IAAI,IAAI,CAAC;IACb,4FAA4F;IAC5F,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,yBAAyB;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yCAAyC;IACzC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC;IAC3E,sCAAsC;IACtC,OAAO,IAAI,IAAI,CAAC;CACjB;AA6BD,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CA6JtE"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Nova Engine — Stepper
3
+ *
4
+ * Multi-step progress indicator with validation,
5
+ * horizontal/vertical layout, and ARIA attributes.
6
+ */
7
+ const STYLE_ID = 'nova-stepper-styles';
8
+ function injectStyles() {
9
+ if (document.getElementById(STYLE_ID))
10
+ return;
11
+ const s = document.createElement('style');
12
+ s.id = STYLE_ID;
13
+ s.textContent = `
14
+ .nova-stepper{display:flex;gap:0;list-style:none;margin:0;padding:0}
15
+ .nova-stepper--vertical{flex-direction:column}
16
+ .nova-stepper-item{display:flex;align-items:center;flex:1;position:relative}
17
+ .nova-stepper--vertical .nova-stepper-item{flex-direction:row;flex:none;padding-bottom:1.5rem}
18
+ .nova-stepper-indicator{width:2rem;height:2rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.875rem;font-weight:600;flex-shrink:0;border:2px solid var(--color-border,rgba(255,255,255,0.15));color:var(--color-text-secondary,rgba(255,255,255,0.5));background:transparent;transition:all 0.2s ease}
19
+ .nova-stepper-item--active .nova-stepper-indicator{border-color:var(--color-accent,#a78bfa);color:var(--color-accent,#a78bfa)}
20
+ .nova-stepper-item--completed .nova-stepper-indicator{border-color:var(--color-success,#34d399);background:var(--color-success,#34d399);color:#fff}
21
+ .nova-stepper-item--error .nova-stepper-indicator{border-color:var(--color-error,#f87171);background:var(--color-error,#f87171);color:#fff}
22
+ .nova-stepper-content{margin-left:0.75rem}
23
+ .nova-stepper-label{font-size:0.875rem;font-weight:500;color:var(--color-text-secondary,rgba(255,255,255,0.5))}
24
+ .nova-stepper-item--active .nova-stepper-label{color:var(--color-text,rgba(255,255,255,0.87))}
25
+ .nova-stepper-item--completed .nova-stepper-label{color:var(--color-text,rgba(255,255,255,0.87))}
26
+ .nova-stepper-description{font-size:0.75rem;color:var(--color-text-secondary,rgba(255,255,255,0.4));margin-top:0.125rem}
27
+ .nova-stepper-connector{flex:1;height:2px;background:var(--color-border,rgba(255,255,255,0.15));margin:0 0.75rem;transition:background 0.2s ease}
28
+ .nova-stepper-item--completed+.nova-stepper-connector,.nova-stepper-connector--completed{background:var(--color-success,#34d399)}
29
+ .nova-stepper--vertical .nova-stepper-connector{width:2px;height:1.5rem;margin:0.25rem 0 0.25rem 0.9375rem;flex:none}
30
+ `;
31
+ document.head.appendChild(s);
32
+ }
33
+ /** Create a multi-step progress indicator. */
34
+ export function createStepper(options) {
35
+ const { container, steps, orientation = 'horizontal', defaultStep = 0, linear = true, onChange, } = options;
36
+ let destroyed = false;
37
+ let current = defaultStep;
38
+ const stepStates = steps.map((_, i) => (i < defaultStep ? 'completed' : i === defaultStep ? 'active' : 'pending'));
39
+ injectStyles();
40
+ // --- Render ---
41
+ const ol = document.createElement('ol');
42
+ ol.className = `nova-stepper nova-stepper--${orientation}`;
43
+ ol.setAttribute('role', 'list');
44
+ const itemEls = [];
45
+ const indicatorEls = [];
46
+ const connectorEls = [];
47
+ for (let i = 0; i < steps.length; i++) {
48
+ const step = steps[i];
49
+ const li = document.createElement('li');
50
+ li.className = 'nova-stepper-item';
51
+ li.setAttribute('role', 'listitem');
52
+ const indicator = document.createElement('span');
53
+ indicator.className = 'nova-stepper-indicator';
54
+ indicator.textContent = step.icon || String(i + 1);
55
+ li.appendChild(indicator);
56
+ indicatorEls.push(indicator);
57
+ const content = document.createElement('span');
58
+ content.className = 'nova-stepper-content';
59
+ const label = document.createElement('span');
60
+ label.className = 'nova-stepper-label';
61
+ label.textContent = step.label;
62
+ content.appendChild(label);
63
+ if (step.description) {
64
+ const desc = document.createElement('span');
65
+ desc.className = 'nova-stepper-description';
66
+ desc.textContent = step.description;
67
+ content.appendChild(desc);
68
+ }
69
+ li.appendChild(content);
70
+ ol.appendChild(li);
71
+ itemEls.push(li);
72
+ // Connector between steps
73
+ if (i < steps.length - 1) {
74
+ const connector = document.createElement('span');
75
+ connector.className = 'nova-stepper-connector';
76
+ connector.setAttribute('aria-hidden', 'true');
77
+ ol.appendChild(connector);
78
+ connectorEls.push(connector);
79
+ }
80
+ }
81
+ container.appendChild(ol);
82
+ updateDisplay();
83
+ function updateDisplay() {
84
+ for (let i = 0; i < steps.length; i++) {
85
+ const item = itemEls[i];
86
+ const indicator = indicatorEls[i];
87
+ item.classList.remove('nova-stepper-item--active', 'nova-stepper-item--completed', 'nova-stepper-item--error');
88
+ const state = stepStates[i];
89
+ if (state === 'active') {
90
+ item.classList.add('nova-stepper-item--active');
91
+ item.setAttribute('aria-current', 'step');
92
+ }
93
+ else {
94
+ item.removeAttribute('aria-current');
95
+ }
96
+ if (state === 'completed') {
97
+ item.classList.add('nova-stepper-item--completed');
98
+ indicator.textContent = '\u2713';
99
+ }
100
+ else if (state === 'error') {
101
+ item.classList.add('nova-stepper-item--error');
102
+ indicator.textContent = '!';
103
+ }
104
+ else {
105
+ indicator.textContent = steps[i].icon || String(i + 1);
106
+ }
107
+ }
108
+ for (let i = 0; i < connectorEls.length; i++) {
109
+ connectorEls[i].classList.toggle('nova-stepper-connector--completed', stepStates[i] === 'completed');
110
+ }
111
+ }
112
+ async function goToStep(index) {
113
+ if (destroyed)
114
+ return false;
115
+ if (index < 0 || index >= steps.length)
116
+ return false;
117
+ if (index === current)
118
+ return true;
119
+ // Linear mode: can only go forward one at a time or backward freely
120
+ if (linear && index > current + 1)
121
+ return false;
122
+ // Validate current step when moving forward
123
+ if (index > current) {
124
+ const step = steps[current];
125
+ if (step.validate) {
126
+ const valid = await step.validate();
127
+ if (!valid) {
128
+ stepStates[current] = 'error';
129
+ updateDisplay();
130
+ return false;
131
+ }
132
+ }
133
+ stepStates[current] = 'completed';
134
+ }
135
+ stepStates[index] = 'active';
136
+ current = index;
137
+ updateDisplay();
138
+ onChange?.(current);
139
+ return true;
140
+ }
141
+ return {
142
+ async next() {
143
+ return goToStep(current + 1);
144
+ },
145
+ prev() {
146
+ if (destroyed || current <= 0)
147
+ return;
148
+ stepStates[current] = 'pending';
149
+ current--;
150
+ stepStates[current] = 'active';
151
+ updateDisplay();
152
+ onChange?.(current);
153
+ },
154
+ goTo(index) {
155
+ return goToStep(index);
156
+ },
157
+ get currentStep() { return current; },
158
+ get stepCount() { return steps.length; },
159
+ setStepState(index, state) {
160
+ if (destroyed || index < 0 || index >= steps.length)
161
+ return;
162
+ stepStates[index] = state;
163
+ updateDisplay();
164
+ },
165
+ destroy() {
166
+ if (destroyed)
167
+ return;
168
+ destroyed = true;
169
+ ol.remove();
170
+ },
171
+ };
172
+ }
173
+ //# sourceMappingURL=stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepper.js","sourceRoot":"","sources":["../../src/stepper/stepper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { createVirtualList } from './virtual-list';
2
+ export type { VirtualListOptions, VirtualListInstance } from './virtual-list';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/virtual-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createVirtualList } from './virtual-list';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/virtual-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Nova Engine — Virtual List
3
+ *
4
+ * DOM-recycling virtualized list for rendering large datasets
5
+ * with fixed or variable row heights.
6
+ */
7
+ export interface VirtualListOptions<T = unknown> {
8
+ /** Scrollable container element */
9
+ container: HTMLElement;
10
+ /** Data items to render */
11
+ items: T[];
12
+ /** Render function — creates a DOM element for an item */
13
+ renderItem: (item: T, index: number) => HTMLElement;
14
+ /** Row height in px, or a function returning height for each index */
15
+ rowHeight: number | ((index: number) => number);
16
+ /** Extra rows rendered above and below the viewport. Default: 5 */
17
+ overscan?: number;
18
+ /** Stable key extractor for efficient updates */
19
+ keyFn?: (item: T) => string;
20
+ }
21
+ export interface VirtualListInstance<T = unknown> {
22
+ /** Scroll to a specific item index */
23
+ scrollTo(index: number, align?: 'start' | 'center' | 'end'): void;
24
+ /** Recalculate heights and redraw (call after external DOM changes) */
25
+ refresh(): void;
26
+ /** Replace the items array and re-render */
27
+ setItems(items: T[]): void;
28
+ /** Get the currently visible index range */
29
+ getVisibleRange(): [number, number];
30
+ /** The scrollable wrapper element */
31
+ readonly element: HTMLElement;
32
+ /** Clean up listeners and DOM */
33
+ destroy(): void;
34
+ }
35
+ /** Create a virtualized list. */
36
+ export declare function createVirtualList<T>(options: VirtualListOptions<T>): VirtualListInstance<T>;
37
+ //# sourceMappingURL=virtual-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-list.d.ts","sourceRoot":"","sources":["../../src/virtual-list/virtual-list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,mCAAmC;IACnC,SAAS,EAAE,WAAW,CAAC;IACvB,2BAA2B;IAC3B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,0DAA0D;IAC1D,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC;IACpD,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAChD,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;IAClE,uEAAuE;IACvE,OAAO,IAAI,IAAI,CAAC;IAChB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;IAC3B,4CAA4C;IAC5C,eAAe,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,iCAAiC;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAyM3F"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Nova Engine — Virtual List
3
+ *
4
+ * DOM-recycling virtualized list for rendering large datasets
5
+ * with fixed or variable row heights.
6
+ */
7
+ /** Create a virtualized list. */
8
+ export function createVirtualList(options) {
9
+ const { container, renderItem, overscan = 5, keyFn, } = options;
10
+ let items = options.items;
11
+ let destroyed = false;
12
+ const isFixedHeight = typeof options.rowHeight === 'number';
13
+ const fixedHeight = isFixedHeight ? options.rowHeight : 0;
14
+ const heightFn = isFixedHeight ? () => fixedHeight : options.rowHeight;
15
+ // --- Prefix sum for variable heights ---
16
+ let offsets = new Float64Array(0);
17
+ function buildOffsets() {
18
+ offsets = new Float64Array(items.length + 1);
19
+ for (let i = 0; i < items.length; i++) {
20
+ offsets[i + 1] = offsets[i] + heightFn(i);
21
+ }
22
+ }
23
+ function totalHeight() {
24
+ if (isFixedHeight)
25
+ return items.length * fixedHeight;
26
+ return offsets[items.length] || 0;
27
+ }
28
+ function getItemOffset(index) {
29
+ if (isFixedHeight)
30
+ return index * fixedHeight;
31
+ return offsets[index] || 0;
32
+ }
33
+ function getItemHeight(index) {
34
+ if (isFixedHeight)
35
+ return fixedHeight;
36
+ return (offsets[index + 1] || 0) - (offsets[index] || 0);
37
+ }
38
+ /** Binary search to find the first item at or after a given offset. */
39
+ function findIndexAtOffset(offset) {
40
+ if (isFixedHeight)
41
+ return Math.floor(offset / fixedHeight);
42
+ let lo = 0, hi = items.length - 1;
43
+ while (lo <= hi) {
44
+ const mid = (lo + hi) >>> 1;
45
+ if (offsets[mid + 1] <= offset)
46
+ lo = mid + 1;
47
+ else if (offsets[mid] > offset)
48
+ hi = mid - 1;
49
+ else
50
+ return mid;
51
+ }
52
+ return lo;
53
+ }
54
+ if (!isFixedHeight)
55
+ buildOffsets();
56
+ // --- DOM setup ---
57
+ const wrapper = document.createElement('div');
58
+ wrapper.style.overflow = 'auto';
59
+ wrapper.style.position = 'relative';
60
+ wrapper.style.width = '100%';
61
+ wrapper.style.height = '100%';
62
+ const spacer = document.createElement('div');
63
+ spacer.style.width = '100%';
64
+ spacer.style.pointerEvents = 'none';
65
+ const viewport = document.createElement('div');
66
+ viewport.style.position = 'absolute';
67
+ viewport.style.top = '0';
68
+ viewport.style.left = '0';
69
+ viewport.style.width = '100%';
70
+ wrapper.appendChild(spacer);
71
+ wrapper.appendChild(viewport);
72
+ container.appendChild(wrapper);
73
+ // --- Render state ---
74
+ let renderedStart = -1;
75
+ let renderedEnd = -1;
76
+ const nodeCache = new Map();
77
+ function render() {
78
+ if (destroyed)
79
+ return;
80
+ const scrollTop = wrapper.scrollTop;
81
+ const viewportHeight = wrapper.clientHeight;
82
+ // Find visible range
83
+ let start = findIndexAtOffset(scrollTop);
84
+ let end = findIndexAtOffset(scrollTop + viewportHeight);
85
+ // Clamp and add overscan
86
+ start = Math.max(0, start - overscan);
87
+ end = Math.min(items.length - 1, end + overscan);
88
+ if (start === renderedStart && end === renderedEnd)
89
+ return;
90
+ renderedStart = start;
91
+ renderedEnd = end;
92
+ // Update spacer height
93
+ spacer.style.height = `${totalHeight()}px`;
94
+ // Collect current nodes for recycling
95
+ const oldKeys = new Set();
96
+ for (const key of nodeCache.keys())
97
+ oldKeys.add(key);
98
+ // Build new content
99
+ const frag = document.createDocumentFragment();
100
+ const newKeys = new Set();
101
+ for (let i = start; i <= end; i++) {
102
+ const key = keyFn ? keyFn(items[i]) : i;
103
+ newKeys.add(key);
104
+ let node = nodeCache.get(key);
105
+ if (!node) {
106
+ node = renderItem(items[i], i);
107
+ nodeCache.set(key, node);
108
+ }
109
+ node.style.position = 'absolute';
110
+ node.style.top = `${getItemOffset(i)}px`;
111
+ node.style.width = '100%';
112
+ node.style.height = `${getItemHeight(i)}px`;
113
+ frag.appendChild(node);
114
+ }
115
+ // Remove nodes no longer visible
116
+ for (const key of oldKeys) {
117
+ if (!newKeys.has(key)) {
118
+ const node = nodeCache.get(key);
119
+ if (node?.parentNode)
120
+ node.remove();
121
+ nodeCache.delete(key);
122
+ }
123
+ }
124
+ viewport.textContent = '';
125
+ viewport.appendChild(frag);
126
+ }
127
+ // --- Scroll handling ---
128
+ let rafId;
129
+ function onScroll() {
130
+ if (rafId)
131
+ cancelAnimationFrame(rafId);
132
+ rafId = requestAnimationFrame(render);
133
+ }
134
+ wrapper.addEventListener('scroll', onScroll, { passive: true });
135
+ // Initial render
136
+ render();
137
+ return {
138
+ scrollTo(index, align = 'start') {
139
+ if (destroyed || index < 0 || index >= items.length)
140
+ return;
141
+ const offset = getItemOffset(index);
142
+ const height = getItemHeight(index);
143
+ const viewportH = wrapper.clientHeight;
144
+ let top = offset;
145
+ if (align === 'center')
146
+ top = offset - viewportH / 2 + height / 2;
147
+ else if (align === 'end')
148
+ top = offset - viewportH + height;
149
+ wrapper.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
150
+ },
151
+ refresh() {
152
+ if (destroyed)
153
+ return;
154
+ if (!isFixedHeight)
155
+ buildOffsets();
156
+ renderedStart = -1;
157
+ renderedEnd = -1;
158
+ nodeCache.clear();
159
+ viewport.textContent = '';
160
+ render();
161
+ },
162
+ setItems(newItems) {
163
+ if (destroyed)
164
+ return;
165
+ items = newItems;
166
+ if (!isFixedHeight)
167
+ buildOffsets();
168
+ renderedStart = -1;
169
+ renderedEnd = -1;
170
+ nodeCache.clear();
171
+ viewport.textContent = '';
172
+ render();
173
+ },
174
+ getVisibleRange() {
175
+ return [Math.max(0, renderedStart), Math.min(items.length - 1, renderedEnd)];
176
+ },
177
+ get element() { return wrapper; },
178
+ destroy() {
179
+ if (destroyed)
180
+ return;
181
+ destroyed = true;
182
+ if (rafId)
183
+ cancelAnimationFrame(rafId);
184
+ wrapper.removeEventListener('scroll', onScroll);
185
+ wrapper.remove();
186
+ nodeCache.clear();
187
+ },
188
+ };
189
+ }
190
+ //# sourceMappingURL=virtual-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-list.js","sourceRoot":"","sources":["../../src/virtual-list/virtual-list.ts"],"names":[],"mappings":"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"}