@praxisjs/devtools 0.1.0 → 0.2.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.
- package/CHANGELOG.md +30 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +1035 -860
- package/package.json +8 -7
- package/src/decorators/debug.ts +102 -77
- package/src/decorators/trace.ts +15 -11
- package/src/icons/ellipsis-vertical.tsx +25 -19
- package/src/icons/panel-bottom.tsx +24 -18
- package/src/icons/panel-left.tsx +24 -18
- package/src/icons/panel-right.tsx +24 -18
- package/src/icons/panel-top.tsx +24 -18
- package/src/icons/x.tsx +24 -18
- package/src/plugins/components/components/component-detail.tsx +59 -54
- package/src/plugins/components/components/component-row.tsx +36 -33
- package/src/plugins/components/components/detail-row.tsx +21 -18
- package/src/plugins/components/components/detail-section.tsx +14 -12
- package/src/plugins/components/components/status-dot.tsx +20 -11
- package/src/plugins/components/components-tab.tsx +66 -61
- package/src/plugins/signals/components/signal-detail.tsx +35 -27
- package/src/plugins/signals/components/signal-row.tsx +32 -28
- package/src/plugins/signals/signals-tab.tsx +92 -79
- package/src/plugins/timeline/components/badge.tsx +15 -9
- package/src/plugins/timeline/components/timeline-row.tsx +52 -45
- package/src/plugins/timeline/timeline-tab.tsx +90 -77
- package/src/plugins/types.ts +2 -2
- package/src/ui/dev-tools.tsx +45 -39
- package/src/ui/panel.tsx +152 -146
- package/src/ui/shared/empty-state.tsx +17 -11
- package/src/ui/shared/icon-button.tsx +28 -25
- package/src/ui/shared/panel-section.tsx +14 -12
- package/src/ui/shared/search-input.tsx +19 -15
- package/src/ui/shared/side-panel.tsx +16 -13
- package/vite.config.ts +3 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisjs/devtools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,17 +12,18 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@unocss/reset": "^66.6.2",
|
|
15
|
-
"@praxisjs/core": "0.
|
|
16
|
-
"@praxisjs/
|
|
17
|
-
"@praxisjs/
|
|
18
|
-
"@praxisjs/
|
|
15
|
+
"@praxisjs/core": "0.3.0",
|
|
16
|
+
"@praxisjs/decorators": "0.3.0",
|
|
17
|
+
"@praxisjs/jsx": "0.2.0",
|
|
18
|
+
"@praxisjs/runtime": "0.2.0",
|
|
19
|
+
"@praxisjs/shared": "0.2.0"
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"@types/node": "^25.3.0",
|
|
22
23
|
"@unocss/cli": "^66.6.2",
|
|
23
|
-
"@unocss/preset-wind3": "^66.6.
|
|
24
|
+
"@unocss/preset-wind3": "^66.6.6",
|
|
24
25
|
"typescript": "^5.9.3",
|
|
25
|
-
"unocss": "^66.6.
|
|
26
|
+
"unocss": "^66.6.6",
|
|
26
27
|
"vite": "^7.3.1",
|
|
27
28
|
"vite-plugin-dts": "^4.5.4"
|
|
28
29
|
},
|
package/src/decorators/debug.ts
CHANGED
|
@@ -41,18 +41,17 @@ interface ComputedSlot {
|
|
|
41
41
|
*/
|
|
42
42
|
export function Debug(options: DebugOptions = {}) {
|
|
43
43
|
return function (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const componentName = (target.constructor as { name: string }).name;
|
|
49
|
-
const label = options.label ?? key;
|
|
44
|
+
value: unknown,
|
|
45
|
+
context: ClassMethodDecoratorContext | ClassFieldDecoratorContext,
|
|
46
|
+
) {
|
|
47
|
+
const label = options.label ?? (context.name as string);
|
|
50
48
|
|
|
51
49
|
// ── Method decorator ─────────────────────────────────────────────────
|
|
52
|
-
if (
|
|
53
|
-
const original =
|
|
50
|
+
if (context.kind === "method") {
|
|
51
|
+
const original = value as (...args: unknown[]) => unknown;
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
return function (this: object, ...args: unknown[]) {
|
|
54
|
+
const componentName = (this.constructor as { name: string }).name;
|
|
56
55
|
const start = performance.now();
|
|
57
56
|
let result: unknown;
|
|
58
57
|
let threw = false;
|
|
@@ -77,85 +76,111 @@ export function Debug(options: DebugOptions = {}) {
|
|
|
77
76
|
|
|
78
77
|
return result;
|
|
79
78
|
};
|
|
80
|
-
|
|
81
|
-
return;
|
|
82
79
|
}
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
enumerable: true,
|
|
113
|
-
configurable: true,
|
|
114
|
-
});
|
|
81
|
+
// ── Field decorator ───────────────────────────────────────────────────
|
|
82
|
+
context.addInitializer(function (
|
|
83
|
+
this: unknown,
|
|
84
|
+
) {
|
|
85
|
+
const instance = this as object & Record<string, unknown>;
|
|
86
|
+
const name = context.name as string;
|
|
87
|
+
const componentName = (
|
|
88
|
+
instance.constructor as { name: string }
|
|
89
|
+
).name;
|
|
90
|
+
|
|
91
|
+
// ── Wrapping @State() getter/setter ─────────────────────────────
|
|
92
|
+
// @State() initializer runs before @Debug() initializer (inner-first),
|
|
93
|
+
// so the getter/setter is already installed on the instance here.
|
|
94
|
+
const existingDesc = Object.getOwnPropertyDescriptor(instance, name);
|
|
95
|
+
|
|
96
|
+
if (existingDesc?.get && existingDesc.set) {
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
98
|
+
const originalGet = existingDesc.get;
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
100
|
+
const originalSet = existingDesc.set;
|
|
101
|
+
|
|
102
|
+
Registry.instance.registerSignal(
|
|
103
|
+
instance,
|
|
104
|
+
label,
|
|
105
|
+
originalGet.call(instance),
|
|
106
|
+
componentName,
|
|
107
|
+
);
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
Object.defineProperty(instance, name, {
|
|
110
|
+
get(this: object) {
|
|
111
|
+
return originalGet.call(this) as unknown;
|
|
112
|
+
},
|
|
113
|
+
set(this: object, newValue: unknown) {
|
|
114
|
+
const oldValue: unknown = originalGet.call(this);
|
|
115
|
+
originalSet.call(this, newValue);
|
|
116
|
+
Registry.instance.updateSignal(this, label, newValue, oldValue);
|
|
117
|
+
},
|
|
118
|
+
enumerable: true,
|
|
119
|
+
configurable: true,
|
|
120
|
+
});
|
|
118
121
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`expected a computed() value but got ${typeof value}. Skipping.`,
|
|
136
|
-
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ── Computed class field ─────────────────────────────────────────
|
|
126
|
+
// The field initializer has already run, so read the assigned value.
|
|
127
|
+
const initialValue = instance[name];
|
|
128
|
+
Reflect.deleteProperty(instance, name);
|
|
129
|
+
|
|
130
|
+
if (!isComputed(initialValue)) {
|
|
131
|
+
if (initialValue !== undefined) {
|
|
132
|
+
console.warn(
|
|
133
|
+
`[PraxisJS DevTools] @Debug() on "${componentName}.${name}": ` +
|
|
134
|
+
`expected a computed() value but got ${typeof initialValue}. Skipping.`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
instance[name] = initialValue;
|
|
137
138
|
return;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
// subscribe() calls the callback immediately (synchronously), so we
|
|
141
142
|
// use a flag to skip the first call and register via registerSignal instead.
|
|
142
|
-
let
|
|
143
|
-
|
|
143
|
+
let slot: ComputedSlot;
|
|
144
|
+
|
|
145
|
+
function subscribe(computed: TrackedComputed): () => void {
|
|
146
|
+
let skipFirst = true;
|
|
147
|
+
let prevValue = computed();
|
|
148
|
+
|
|
149
|
+
const unsub = computed.subscribe((newValue) => {
|
|
150
|
+
if (skipFirst) {
|
|
151
|
+
skipFirst = false;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
Registry.instance.updateSignal(instance, label, newValue, prevValue);
|
|
155
|
+
prevValue = newValue;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
Registry.instance.registerSignal(instance, label, prevValue, componentName);
|
|
159
|
+
return unsub;
|
|
160
|
+
}
|
|
144
161
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
slot = { computed: initialValue, unsub: subscribe(initialValue) };
|
|
163
|
+
|
|
164
|
+
Object.defineProperty(instance, name, {
|
|
165
|
+
get() {
|
|
166
|
+
return slot.computed;
|
|
167
|
+
},
|
|
168
|
+
set(newValue: unknown) {
|
|
169
|
+
slot.unsub();
|
|
170
|
+
|
|
171
|
+
if (!isComputed(newValue)) {
|
|
172
|
+
console.warn(
|
|
173
|
+
`[PraxisJS DevTools] @Debug() on "${componentName}.${name}": ` +
|
|
174
|
+
`expected a computed() value but got ${typeof newValue}. Skipping.`,
|
|
175
|
+
);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
slot = { computed: newValue, unsub: subscribe(newValue) };
|
|
180
|
+
},
|
|
181
|
+
enumerable: true,
|
|
182
|
+
configurable: true,
|
|
152
183
|
});
|
|
153
|
-
|
|
154
|
-
slots.set(this, { computed: value, unsub });
|
|
155
|
-
Registry.instance.registerSignal(this, label, prevValue, componentName);
|
|
156
|
-
},
|
|
157
|
-
enumerable: true,
|
|
158
|
-
configurable: true,
|
|
159
184
|
});
|
|
160
185
|
};
|
|
161
186
|
}
|
package/src/decorators/trace.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Registry } from
|
|
1
|
+
import { Registry } from "../core/registry";
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
4
|
type AnyConstructor = new (...args: any[]) => any;
|
|
@@ -9,16 +9,18 @@ type AnyConstructor = new (...args: any[]) => any;
|
|
|
9
9
|
*
|
|
10
10
|
* @Trace()
|
|
11
11
|
* @Component()
|
|
12
|
-
* class MyComponent extends
|
|
12
|
+
* class MyComponent extends StatefulComponent { ... }
|
|
13
13
|
*/
|
|
14
14
|
export function Trace() {
|
|
15
|
-
return function <T extends AnyConstructor>(constructor: T): T {
|
|
15
|
+
return function <T extends AnyConstructor>(constructor: T, _context: ClassDecoratorContext): T {
|
|
16
16
|
const name = constructor.name;
|
|
17
17
|
const registry = Registry.instance;
|
|
18
18
|
const proto = constructor.prototype as Record<string, unknown>;
|
|
19
19
|
|
|
20
20
|
// ── render() ──────────────────────────────────────────────────────────
|
|
21
|
-
const originalRender = proto.render as
|
|
21
|
+
const originalRender = proto.render as
|
|
22
|
+
| ((...args: unknown[]) => unknown)
|
|
23
|
+
| undefined;
|
|
22
24
|
|
|
23
25
|
if (originalRender) {
|
|
24
26
|
proto.render = function (this: object, ...args: unknown[]) {
|
|
@@ -37,21 +39,23 @@ export function Trace() {
|
|
|
37
39
|
|
|
38
40
|
proto.onBeforeMount = function (this: object, ...args: unknown[]) {
|
|
39
41
|
registry.registerComponent(this, name);
|
|
40
|
-
registry.recordLifecycle(this,
|
|
42
|
+
registry.recordLifecycle(this, "onBeforeMount");
|
|
41
43
|
return originalOnBeforeMount?.call(this, ...args);
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
// ── remaining lifecycle hooks ─────────────────────────────────────────
|
|
45
47
|
const hooks = [
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
"onMount",
|
|
49
|
+
"onUnmount",
|
|
50
|
+
"onBeforeUpdate",
|
|
51
|
+
"onUpdate",
|
|
52
|
+
"onAfterUpdate",
|
|
51
53
|
] as const;
|
|
52
54
|
|
|
53
55
|
for (const hook of hooks) {
|
|
54
|
-
const original = proto[hook] as
|
|
56
|
+
const original = proto[hook] as
|
|
57
|
+
| ((...args: unknown[]) => unknown)
|
|
58
|
+
| undefined;
|
|
55
59
|
|
|
56
60
|
proto[hook] = function (this: object, ...args: unknown[]) {
|
|
57
61
|
registry.recordLifecycle(this, hook);
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class EllipsisVerticalIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-ellipsis-vertical-icon lucide-ellipsis-vertical"
|
|
19
|
+
>
|
|
20
|
+
<circle cx="12" cy="12" r="1" />
|
|
21
|
+
<circle cx="12" cy="5" r="1" />
|
|
22
|
+
<circle cx="12" cy="19" r="1" />
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
20
26
|
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class PanelBottomIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-panel-bottom-icon lucide-panel-bottom"
|
|
19
|
+
>
|
|
20
|
+
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
21
|
+
<path d="M3 15h18" />
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
19
25
|
}
|
package/src/icons/panel-left.tsx
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class PanelLeftIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-panel-left-icon lucide-panel-left"
|
|
19
|
+
>
|
|
20
|
+
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
21
|
+
<path d="M9 3v18" />
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
19
25
|
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class PanelRightIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-panel-right-icon lucide-panel-right"
|
|
19
|
+
>
|
|
20
|
+
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
21
|
+
<path d="M15 3v18" />
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
19
25
|
}
|
package/src/icons/panel-top.tsx
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class PanelTopIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-panel-top-icon lucide-panel-top"
|
|
19
|
+
>
|
|
20
|
+
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
21
|
+
<path d="M3 9h18" />
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
19
25
|
}
|
package/src/icons/x.tsx
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { StatelessComponent } from "@praxisjs/core";
|
|
2
|
+
import { Component } from "@praxisjs/decorators";
|
|
3
|
+
|
|
4
|
+
@Component()
|
|
5
|
+
export class XIcon extends StatelessComponent {
|
|
6
|
+
render() {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
width="24"
|
|
11
|
+
height="24"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="2"
|
|
16
|
+
stroke-linecap="round"
|
|
17
|
+
stroke-linejoin="round"
|
|
18
|
+
class="lucide lucide-x-icon lucide-x"
|
|
19
|
+
>
|
|
20
|
+
<path d="M18 6 6 18" />
|
|
21
|
+
<path d="m6 6 12 12" />
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
19
25
|
}
|