@keenthemes/ktui 1.2.3 → 1.2.5
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.
- package/dist/ktui.js +2244 -1061
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +185 -40
- package/lib/cjs/components/context-menu/context-menu.d.ts +66 -0
- package/lib/cjs/components/context-menu/context-menu.d.ts.map +1 -0
- package/lib/cjs/components/context-menu/context-menu.js +423 -0
- package/lib/cjs/components/context-menu/context-menu.js.map +1 -0
- package/lib/cjs/components/context-menu/index.d.ts +7 -0
- package/lib/cjs/components/context-menu/index.d.ts.map +1 -0
- package/lib/cjs/components/context-menu/index.js +10 -0
- package/lib/cjs/components/context-menu/index.js.map +1 -0
- package/lib/cjs/components/context-menu/types.d.ts +30 -0
- package/lib/cjs/components/context-menu/types.d.ts.map +1 -0
- package/lib/cjs/components/context-menu/types.js +7 -0
- package/lib/cjs/components/context-menu/types.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +34 -15
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-contracts.d.ts +66 -0
- package/lib/cjs/components/datatable/datatable-contracts.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-contracts.js +7 -0
- package/lib/cjs/components/datatable/datatable-contracts.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-event-adapter.d.ts +7 -0
- package/lib/cjs/components/datatable/datatable-event-adapter.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-event-adapter.js +16 -0
- package/lib/cjs/components/datatable/datatable-event-adapter.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts +25 -0
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-local-provider.js +190 -0
- package/lib/cjs/components/datatable/datatable-local-provider.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts +15 -0
- package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js +144 -0
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.d.ts +25 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.js +191 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-state-store.d.ts +21 -0
- package/lib/cjs/components/datatable/datatable-state-store.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-state-store.js +81 -0
- package/lib/cjs/components/datatable/datatable-state-store.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts +16 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.js +141 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.d.ts +9 -87
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +234 -740
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.d.ts +2 -2
- package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +68 -31
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/input-number/index.d.ts +7 -0
- package/lib/cjs/components/input-number/index.d.ts.map +1 -0
- package/lib/cjs/components/input-number/index.js +10 -0
- package/lib/cjs/components/input-number/index.js.map +1 -0
- package/lib/cjs/components/input-number/input-number.d.ts +40 -0
- package/lib/cjs/components/input-number/input-number.d.ts.map +1 -0
- package/lib/cjs/components/input-number/input-number.js +248 -0
- package/lib/cjs/components/input-number/input-number.js.map +1 -0
- package/lib/cjs/components/input-number/types.d.ts +30 -0
- package/lib/cjs/components/input-number/types.d.ts.map +1 -0
- package/lib/cjs/components/input-number/types.js +7 -0
- package/lib/cjs/components/input-number/types.js.map +1 -0
- package/lib/cjs/components/select/config.d.ts +1 -0
- package/lib/cjs/components/select/config.d.ts.map +1 -1
- package/lib/cjs/components/select/config.js +2 -1
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/index.d.ts +1 -1
- package/lib/cjs/components/select/index.d.ts.map +1 -1
- package/lib/cjs/components/select/select.d.ts +8 -1
- package/lib/cjs/components/select/select.d.ts.map +1 -1
- package/lib/cjs/components/select/select.js +14 -1
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.d.ts.map +1 -1
- package/lib/cjs/components/select/tags.js +10 -0
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/index.d.ts +9 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +11 -7
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/init-all.d.ts +6 -0
- package/lib/cjs/init-all.d.ts.map +1 -0
- package/lib/cjs/init-all.js +17 -0
- package/lib/cjs/init-all.js.map +1 -0
- package/lib/cjs/legacy.d.ts +8 -0
- package/lib/cjs/legacy.d.ts.map +1 -0
- package/lib/cjs/legacy.js +26 -0
- package/lib/cjs/legacy.js.map +1 -0
- package/lib/esm/components/context-menu/context-menu.d.ts +66 -0
- package/lib/esm/components/context-menu/context-menu.d.ts.map +1 -0
- package/lib/esm/components/context-menu/context-menu.js +420 -0
- package/lib/esm/components/context-menu/context-menu.js.map +1 -0
- package/lib/esm/components/context-menu/index.d.ts +7 -0
- package/lib/esm/components/context-menu/index.d.ts.map +1 -0
- package/lib/esm/components/context-menu/index.js +6 -0
- package/lib/esm/components/context-menu/index.js.map +1 -0
- package/lib/esm/components/context-menu/types.d.ts +30 -0
- package/lib/esm/components/context-menu/types.d.ts.map +1 -0
- package/lib/esm/components/context-menu/types.js +6 -0
- package/lib/esm/components/context-menu/types.js.map +1 -0
- package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +34 -15
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/esm/components/datatable/datatable-contracts.d.ts +66 -0
- package/lib/esm/components/datatable/datatable-contracts.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-contracts.js +6 -0
- package/lib/esm/components/datatable/datatable-contracts.js.map +1 -0
- package/lib/esm/components/datatable/datatable-event-adapter.d.ts +7 -0
- package/lib/esm/components/datatable/datatable-event-adapter.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-event-adapter.js +13 -0
- package/lib/esm/components/datatable/datatable-event-adapter.js.map +1 -0
- package/lib/esm/components/datatable/datatable-local-provider.d.ts +25 -0
- package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-local-provider.js +187 -0
- package/lib/esm/components/datatable/datatable-local-provider.js.map +1 -0
- package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts +15 -0
- package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-pagination-renderer.js +141 -0
- package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -0
- package/lib/esm/components/datatable/datatable-remote-provider.d.ts +25 -0
- package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-remote-provider.js +188 -0
- package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -0
- package/lib/esm/components/datatable/datatable-state-store.d.ts +21 -0
- package/lib/esm/components/datatable/datatable-state-store.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-state-store.js +78 -0
- package/lib/esm/components/datatable/datatable-state-store.js.map +1 -0
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts +16 -0
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-table-renderer.js +138 -0
- package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -0
- package/lib/esm/components/datatable/datatable.d.ts +9 -87
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +234 -740
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.d.ts +2 -2
- package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +68 -31
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/input-number/index.d.ts +7 -0
- package/lib/esm/components/input-number/index.d.ts.map +1 -0
- package/lib/esm/components/input-number/index.js +6 -0
- package/lib/esm/components/input-number/index.js.map +1 -0
- package/lib/esm/components/input-number/input-number.d.ts +40 -0
- package/lib/esm/components/input-number/input-number.d.ts.map +1 -0
- package/lib/esm/components/input-number/input-number.js +245 -0
- package/lib/esm/components/input-number/input-number.js.map +1 -0
- package/lib/esm/components/input-number/types.d.ts +30 -0
- package/lib/esm/components/input-number/types.d.ts.map +1 -0
- package/lib/esm/components/input-number/types.js +6 -0
- package/lib/esm/components/input-number/types.js.map +1 -0
- package/lib/esm/components/select/config.d.ts +1 -0
- package/lib/esm/components/select/config.d.ts.map +1 -1
- package/lib/esm/components/select/config.js +2 -1
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/index.d.ts +1 -1
- package/lib/esm/components/select/index.d.ts.map +1 -1
- package/lib/esm/components/select/select.d.ts +8 -1
- package/lib/esm/components/select/select.d.ts.map +1 -1
- package/lib/esm/components/select/select.js +14 -1
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.d.ts.map +1 -1
- package/lib/esm/components/select/tags.js +11 -1
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/index.d.ts +9 -1
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +7 -5
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/init-all.d.ts +6 -0
- package/lib/esm/init-all.d.ts.map +1 -0
- package/lib/esm/init-all.js +13 -0
- package/lib/esm/init-all.js.map +1 -0
- package/lib/esm/legacy.d.ts +8 -0
- package/lib/esm/legacy.d.ts.map +1 -0
- package/lib/esm/legacy.js +8 -0
- package/lib/esm/legacy.js.map +1 -0
- package/package.json +35 -11
- package/src/__tests__/entrypoints.test.ts +71 -0
- package/src/components/context-menu/__tests__/context-menu.test.ts +117 -0
- package/src/components/context-menu/context-menu.css +32 -0
- package/src/components/context-menu/context-menu.ts +529 -0
- package/src/components/context-menu/index.ts +10 -0
- package/src/components/context-menu/types.ts +32 -0
- package/src/components/datatable/__tests__/architecture-boundaries.test.ts +259 -0
- package/src/components/datatable/datatable-checkbox.ts +34 -23
- package/src/components/datatable/datatable-contracts.ts +96 -0
- package/src/components/datatable/datatable-event-adapter.ts +21 -0
- package/src/components/datatable/datatable-local-provider.ts +193 -0
- package/src/components/datatable/datatable-pagination-renderer.ts +225 -0
- package/src/components/datatable/datatable-remote-provider.ts +178 -0
- package/src/components/datatable/datatable-state-store.ts +94 -0
- package/src/components/datatable/datatable-table-renderer.ts +214 -0
- package/src/components/datatable/datatable.ts +250 -918
- package/src/components/dropdown/dropdown.ts +86 -58
- package/src/components/input/input-group.css +14 -1
- package/src/components/input-number/__tests__/input-number.test.ts +278 -0
- package/src/components/input-number/index.ts +11 -0
- package/src/components/input-number/input-number.ts +267 -0
- package/src/components/input-number/types.ts +32 -0
- package/src/components/select/__tests__/ux-behaviors.test.ts +72 -0
- package/src/components/select/config.ts +3 -1
- package/src/components/select/index.ts +1 -1
- package/src/components/select/select.css +23 -20
- package/src/components/select/select.ts +15 -1
- package/src/components/select/tags.ts +14 -1
- package/src/index.ts +18 -5
- package/src/init-all.ts +15 -0
- package/src/legacy.ts +9 -0
- package/styles.css +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keenthemes/ktui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Free & Open-Source Tailwind UI Components by Keenthemes",
|
|
5
5
|
"homepage": "https://ktui.io",
|
|
6
6
|
"repository": {
|
|
@@ -52,9 +52,36 @@
|
|
|
52
52
|
"tailwind clipboard"
|
|
53
53
|
],
|
|
54
54
|
"author": "@keenthemes",
|
|
55
|
-
"types": "lib/esm/
|
|
56
|
-
"main": "lib/cjs/
|
|
57
|
-
"module": "lib/esm/
|
|
55
|
+
"types": "lib/esm/legacy.d.ts",
|
|
56
|
+
"main": "lib/cjs/legacy.js",
|
|
57
|
+
"module": "lib/esm/legacy.js",
|
|
58
|
+
"exports": {
|
|
59
|
+
".": {
|
|
60
|
+
"types": "./lib/esm/legacy.d.ts",
|
|
61
|
+
"import": "./lib/esm/legacy.js",
|
|
62
|
+
"require": "./lib/cjs/legacy.js"
|
|
63
|
+
},
|
|
64
|
+
"./core": {
|
|
65
|
+
"types": "./lib/esm/index.d.ts",
|
|
66
|
+
"import": "./lib/esm/index.js",
|
|
67
|
+
"require": "./lib/cjs/index.js"
|
|
68
|
+
},
|
|
69
|
+
"./init-all": {
|
|
70
|
+
"types": "./lib/esm/init-all.d.ts",
|
|
71
|
+
"import": "./lib/esm/init-all.js",
|
|
72
|
+
"require": "./lib/cjs/init-all.js"
|
|
73
|
+
},
|
|
74
|
+
"./components/*": {
|
|
75
|
+
"types": "./lib/esm/components/*/index.d.ts",
|
|
76
|
+
"import": "./lib/esm/components/*/index.js",
|
|
77
|
+
"require": "./lib/cjs/components/*/index.js"
|
|
78
|
+
},
|
|
79
|
+
"./src/*": "./src/*",
|
|
80
|
+
"./lib/*": "./lib/*",
|
|
81
|
+
"./styles.css": "./styles.css",
|
|
82
|
+
"./dist/*": "./dist/*",
|
|
83
|
+
"./package.json": "./package.json"
|
|
84
|
+
},
|
|
58
85
|
"license": "MIT",
|
|
59
86
|
"files": [
|
|
60
87
|
"dist",
|
|
@@ -94,19 +121,14 @@
|
|
|
94
121
|
"publish:github": "npm publish"
|
|
95
122
|
},
|
|
96
123
|
"devDependencies": {
|
|
97
|
-
"@babel/core": "^7.27.3",
|
|
98
|
-
"@babel/preset-env": "^7.27.2",
|
|
99
124
|
"@eslint/js": "^9.27.0",
|
|
100
125
|
"@types/jsdom": "^21.1.7",
|
|
101
126
|
"@types/node": "^22.15.23",
|
|
102
127
|
"@vitest/ui": "^4.0.16",
|
|
103
|
-
"autoprefixer": "^10.4.21",
|
|
104
|
-
"babel-loader": "^10.0.0",
|
|
105
128
|
"concurrently": "^9.1.2",
|
|
106
129
|
"eslint": "^10.0.0",
|
|
107
130
|
"eslint-plugin-prettier": "^5.4.0",
|
|
108
131
|
"jsdom": "^25.0.1",
|
|
109
|
-
"mini-svg-data-uri": "^1.4.4",
|
|
110
132
|
"prettier": "^3.5.3",
|
|
111
133
|
"source-map-loader": "^5.0.0",
|
|
112
134
|
"tailwindcss": "^4.1.11",
|
|
@@ -116,14 +138,16 @@
|
|
|
116
138
|
"typescript-eslint": "^8.18.0",
|
|
117
139
|
"vitest": "^4.0.16",
|
|
118
140
|
"webpack": "^5.99.9",
|
|
119
|
-
"webpack-cli": "^6.0.1"
|
|
120
|
-
"webpack-merge-and-include-globally": "^1.0.7"
|
|
141
|
+
"webpack-cli": "^6.0.1"
|
|
121
142
|
},
|
|
122
143
|
"dependencies": {
|
|
123
144
|
"@popperjs/core": "^2.11.8"
|
|
124
145
|
},
|
|
125
146
|
"overrides": {
|
|
147
|
+
"brace-expansion": "^5.0.6",
|
|
148
|
+
"fast-uri": "^3.1.2",
|
|
126
149
|
"minimatch": "^10.2.3",
|
|
150
|
+
"postcss": "^8.5.14",
|
|
127
151
|
"rollup": "^4.59.0",
|
|
128
152
|
"serialize-javascript": "^7.0.3",
|
|
129
153
|
"terser-webpack-plugin": "^5.3.17"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
|
|
3
|
+
describe('KTUI entrypoints', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.restoreAllMocks();
|
|
6
|
+
vi.resetModules();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('component-level import does not initialize unrelated components', async () => {
|
|
10
|
+
const { KTModal } = await import('../components/modal');
|
|
11
|
+
const modalInitSpy = vi.spyOn(KTModal, 'init');
|
|
12
|
+
const coreModule = await import('../index');
|
|
13
|
+
const componentsInitSpy = vi.spyOn(coreModule.KTComponents, 'init');
|
|
14
|
+
|
|
15
|
+
await import('../components/toggle-password');
|
|
16
|
+
|
|
17
|
+
expect(modalInitSpy).not.toHaveBeenCalled();
|
|
18
|
+
expect(componentsInitSpy).not.toHaveBeenCalled();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('core entrypoint import is side-effect-free', async () => {
|
|
22
|
+
const domModule = await import('../helpers/dom');
|
|
23
|
+
const readySpy = vi.spyOn(domModule.default, 'ready');
|
|
24
|
+
|
|
25
|
+
const coreModule = await import('../index');
|
|
26
|
+
const initSpy = vi.spyOn(coreModule.KTComponents, 'init');
|
|
27
|
+
|
|
28
|
+
expect(readySpy).not.toHaveBeenCalled();
|
|
29
|
+
expect(initSpy).not.toHaveBeenCalled();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('init-all entrypoint initializes components explicitly', async () => {
|
|
33
|
+
const domModule = await import('../helpers/dom');
|
|
34
|
+
const readySpy = vi
|
|
35
|
+
.spyOn(domModule.default, 'ready')
|
|
36
|
+
.mockImplementation((callback) => {
|
|
37
|
+
callback();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const coreModule = await import('../index');
|
|
41
|
+
const initSpy = vi.spyOn(coreModule.KTComponents, 'init');
|
|
42
|
+
|
|
43
|
+
const initAllModule = await import('../init-all');
|
|
44
|
+
|
|
45
|
+
expect(readySpy).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(initSpy).toHaveBeenCalledTimes(1);
|
|
47
|
+
|
|
48
|
+
initAllModule.initAllComponents();
|
|
49
|
+
expect(readySpy).toHaveBeenCalledTimes(2);
|
|
50
|
+
expect(initSpy).toHaveBeenCalledTimes(2);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('legacy root entrypoint preserves auto-init behavior', async () => {
|
|
54
|
+
const domModule = await import('../helpers/dom');
|
|
55
|
+
const readySpy = vi
|
|
56
|
+
.spyOn(domModule.default, 'ready')
|
|
57
|
+
.mockImplementation((callback) => {
|
|
58
|
+
callback();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const coreModule = await import('../index');
|
|
62
|
+
const initSpy = vi.spyOn(coreModule.KTComponents, 'init');
|
|
63
|
+
|
|
64
|
+
const legacyModule = await import('../legacy');
|
|
65
|
+
|
|
66
|
+
expect(initSpy).toHaveBeenCalled();
|
|
67
|
+
expect(readySpy).toHaveBeenCalled();
|
|
68
|
+
expect(legacyModule.default).toBe(coreModule.default);
|
|
69
|
+
expect(legacyModule.KTComponents).toBe(coreModule.KTComponents);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { KTContextMenu } from '../context-menu';
|
|
3
|
+
|
|
4
|
+
const mockDestroy = vi.fn();
|
|
5
|
+
const mockForceUpdate = vi.fn();
|
|
6
|
+
|
|
7
|
+
vi.mock('@popperjs/core', () => ({
|
|
8
|
+
createPopper: vi.fn(() => ({
|
|
9
|
+
destroy: mockDestroy,
|
|
10
|
+
forceUpdate: mockForceUpdate,
|
|
11
|
+
})),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
function waitForTransitions() {
|
|
15
|
+
return new Promise<void>((resolve) => {
|
|
16
|
+
setTimeout(() => resolve(), 5);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createFixture() {
|
|
21
|
+
document.body.innerHTML = `
|
|
22
|
+
<div id="root" data-kt-context-menu="true">
|
|
23
|
+
<div id="trigger" data-kt-context-menu-trigger="true">target</div>
|
|
24
|
+
<div id="menu" data-kt-context-menu-menu="true" class="kt-context-menu hidden">
|
|
25
|
+
<button id="dismiss" data-kt-context-menu-dismiss="true">dismiss</button>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
root: document.getElementById('root') as HTMLElement,
|
|
32
|
+
trigger: document.getElementById('trigger') as HTMLElement,
|
|
33
|
+
menu: document.getElementById('menu') as HTMLElement,
|
|
34
|
+
dismiss: document.getElementById('dismiss') as HTMLElement,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('KTContextMenu', () => {
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
document.body.innerHTML = '';
|
|
41
|
+
mockDestroy.mockClear();
|
|
42
|
+
mockForceUpdate.mockClear();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
document.body.innerHTML = '';
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('creates and retrieves an instance', () => {
|
|
50
|
+
const { root } = createFixture();
|
|
51
|
+
const instance = new KTContextMenu(root);
|
|
52
|
+
expect(instance.getElement()).toBe(root);
|
|
53
|
+
expect(KTContextMenu.getInstance(root)).toBe(instance);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('opens from showAtEvent and prevents native menu by default', () => {
|
|
57
|
+
const { root } = createFixture();
|
|
58
|
+
const instance = new KTContextMenu(root);
|
|
59
|
+
const event = new MouseEvent('contextmenu', {
|
|
60
|
+
bubbles: true,
|
|
61
|
+
cancelable: true,
|
|
62
|
+
clientX: 100,
|
|
63
|
+
clientY: 120,
|
|
64
|
+
});
|
|
65
|
+
const preventDefaultSpy = vi.spyOn(event, 'preventDefault');
|
|
66
|
+
instance.showAtEvent(event);
|
|
67
|
+
|
|
68
|
+
expect(instance.isOpen()).toBe(true);
|
|
69
|
+
expect(preventDefaultSpy).toHaveBeenCalled();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('hide closes an open menu', async () => {
|
|
73
|
+
const { root } = createFixture();
|
|
74
|
+
const instance = new KTContextMenu(root);
|
|
75
|
+
|
|
76
|
+
instance.showAt(60, 60);
|
|
77
|
+
expect(instance.isOpen()).toBe(true);
|
|
78
|
+
(instance as unknown as { _shownAt: number })._shownAt = Date.now() - 300;
|
|
79
|
+
(instance as unknown as { _isOpen: boolean })._isOpen = true;
|
|
80
|
+
|
|
81
|
+
instance.hide();
|
|
82
|
+
await waitForTransitions();
|
|
83
|
+
expect(instance.isOpen()).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('toggleAtEvent toggles menu state', async () => {
|
|
87
|
+
const { root } = createFixture();
|
|
88
|
+
const instance = new KTContextMenu(root);
|
|
89
|
+
|
|
90
|
+
const openEvent = new MouseEvent('contextmenu', {
|
|
91
|
+
bubbles: true,
|
|
92
|
+
cancelable: true,
|
|
93
|
+
clientX: 30,
|
|
94
|
+
clientY: 30,
|
|
95
|
+
});
|
|
96
|
+
instance.toggleAtEvent(openEvent);
|
|
97
|
+
expect(instance.isOpen()).toBe(true);
|
|
98
|
+
(instance as unknown as { _shownAt: number })._shownAt = Date.now() - 300;
|
|
99
|
+
(instance as unknown as { _isOpen: boolean })._isOpen = true;
|
|
100
|
+
|
|
101
|
+
instance.toggleAtEvent(openEvent);
|
|
102
|
+
await waitForTransitions();
|
|
103
|
+
expect(instance.isOpen()).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('reinit rebuilds instances for existing roots', () => {
|
|
107
|
+
const { root } = createFixture();
|
|
108
|
+
new KTContextMenu(root);
|
|
109
|
+
const first = KTContextMenu.getInstance(root);
|
|
110
|
+
expect(first).not.toBeNull();
|
|
111
|
+
|
|
112
|
+
KTContextMenu.reinit();
|
|
113
|
+
const second = KTContextMenu.getInstance(root);
|
|
114
|
+
expect(second).not.toBeNull();
|
|
115
|
+
expect(second).not.toBe(first);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
@layer components {
|
|
7
|
+
.kt-context-menu {
|
|
8
|
+
@apply p-1.5 space-y-0.5 rounded-md shadow-md shadow-[rgba(0,0,0,0.05)] border border-border bg-popover text-popover-foreground;
|
|
9
|
+
|
|
10
|
+
&:not(.open) {
|
|
11
|
+
@apply hidden;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.kt-context-menu-sub {
|
|
16
|
+
@apply space-y-1 w-full;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.kt-context-menu-toggle {
|
|
20
|
+
@apply w-full flex items-center gap-x-2 py-1.5 px-2 rounded-md font-medium text-sm text-start cursor-pointer disabled:opacity-50 disabled:pointer-events-none;
|
|
21
|
+
@apply text-foreground hover:bg-accent hover:text-accent-foreground;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.kt-context-menu-link {
|
|
25
|
+
@apply w-full flex items-center gap-x-2 py-1.5 px-2 rounded-md font-medium text-sm text-start cursor-pointer disabled:opacity-50 disabled:pointer-events-none;
|
|
26
|
+
@apply text-foreground hover:bg-accent hover:text-accent-foreground;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.kt-context-menu-separator {
|
|
30
|
+
@apply h-px bg-border my-2.5 -mx-2 rtl:transform rtl:rotate-180;
|
|
31
|
+
}
|
|
32
|
+
}
|