oxiui-lib 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.
Files changed (64) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +15 -0
  3. package/biome.json +34 -0
  4. package/bun.lock +71 -0
  5. package/dist/core/elements/AbaComponent.d.ts +36 -0
  6. package/dist/core/elements/AbaComponent.js +114 -0
  7. package/dist/core/elements/AbaStateFull.d.ts +20 -0
  8. package/dist/core/elements/AbaStateFull.js +7 -0
  9. package/dist/core/elements/Animation.d.ts +31 -0
  10. package/dist/core/elements/Animation.js +83 -0
  11. package/dist/core/elements/Button.d.ts +23 -0
  12. package/dist/core/elements/Button.js +15 -0
  13. package/dist/core/elements/HRow.d.ts +4 -0
  14. package/dist/core/elements/HRow.js +11 -0
  15. package/dist/core/elements/InputText.d.ts +25 -0
  16. package/dist/core/elements/InputText.js +28 -0
  17. package/dist/core/elements/Stack.d.ts +26 -0
  18. package/dist/core/elements/Stack.js +40 -0
  19. package/dist/core/elements/Text.d.ts +40 -0
  20. package/dist/core/elements/Text.js +45 -0
  21. package/dist/core/elements/VRow.d.ts +4 -0
  22. package/dist/core/elements/VRow.js +11 -0
  23. package/dist/core/elements/index.d.ts +10 -0
  24. package/dist/core/elements/index.js +26 -0
  25. package/dist/core/elements/ui.d.ts +1 -0
  26. package/dist/core/elements/ui.js +6 -0
  27. package/dist/core/renderer.d.ts +3 -0
  28. package/dist/core/renderer.js +15 -0
  29. package/dist/core/renderers/html.d.ts +22 -0
  30. package/dist/core/renderers/html.js +201 -0
  31. package/dist/core/scheduler.d.ts +10 -0
  32. package/dist/core/scheduler.js +102 -0
  33. package/dist/core/signals.d.ts +13 -0
  34. package/dist/core/signals.js +77 -0
  35. package/dist/core/tree.d.ts +5 -0
  36. package/dist/core/tree.js +18 -0
  37. package/dist/core/types/component.d.ts +21 -0
  38. package/dist/core/types/component.js +2 -0
  39. package/dist/core/types/html.d.ts +66 -0
  40. package/dist/core/types/html.js +27 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.js +19 -0
  43. package/lefthook.yml +6 -0
  44. package/package.json +23 -0
  45. package/src/core/elements/Animation.ts +80 -0
  46. package/src/core/elements/Button.ts +14 -0
  47. package/src/core/elements/HRow.ts +8 -0
  48. package/src/core/elements/InputText.ts +25 -0
  49. package/src/core/elements/OxiComponent.ts +143 -0
  50. package/src/core/elements/OxiStateFull.ts +3 -0
  51. package/src/core/elements/Stack.ts +44 -0
  52. package/src/core/elements/Text.ts +53 -0
  53. package/src/core/elements/VRow.ts +8 -0
  54. package/src/core/elements/index.ts +10 -0
  55. package/src/core/elements/ui.ts +5 -0
  56. package/src/core/renderer.ts +12 -0
  57. package/src/core/renderers/html.ts +268 -0
  58. package/src/core/scheduler.ts +124 -0
  59. package/src/core/signals.ts +84 -0
  60. package/src/core/tree.ts +20 -0
  61. package/src/core/types/component.ts +25 -0
  62. package/src/core/types/html.ts +97 -0
  63. package/src/index.ts +3 -0
  64. package/tsconfig.json +12 -0
@@ -0,0 +1,13 @@
1
+ export declare class Signal<T> {
2
+ #private;
3
+ initial: T;
4
+ constructor(initial: T);
5
+ private state;
6
+ private cursor;
7
+ get value(): T;
8
+ set value(v: T);
9
+ private static clearReaders;
10
+ private static getCurrentReaderWithCursorId;
11
+ private static getReadersWithCursor;
12
+ static create<T>(initial: T): [() => T, (v: T) => void];
13
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _a, _Signal_memory, _Signal_readers;
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.Signal = void 0;
10
+ const renderer_js_1 = require("./renderer.js");
11
+ const scheduler_js_1 = require("./scheduler.js");
12
+ const tree_js_1 = require("./tree.js");
13
+ class Signal {
14
+ constructor(initial) {
15
+ this.initial = initial;
16
+ this.cursor = (0, renderer_js_1.nextCursor)();
17
+ if (!__classPrivateFieldGet(_a, _a, "f", _Signal_memory).has(this.cursor)) {
18
+ __classPrivateFieldGet(_a, _a, "f", _Signal_memory).set(this.cursor, { value: initial });
19
+ }
20
+ this.state = __classPrivateFieldGet(_a, _a, "f", _Signal_memory).get(this.cursor);
21
+ }
22
+ get value() {
23
+ const reader = _a.getCurrentReaderWithCursorId(this.cursor);
24
+ if (!__classPrivateFieldGet(_a, _a, "f", _Signal_readers).has(reader)) {
25
+ __classPrivateFieldGet(_a, _a, "f", _Signal_readers).add(reader);
26
+ }
27
+ return this.state.value;
28
+ }
29
+ set value(v) {
30
+ this.state.value = v;
31
+ if (this.cursor) {
32
+ (0, scheduler_js_1.rerender)(`${this.cursor}`, _a.getReadersWithCursor(this.cursor));
33
+ console.log(this.cursor, (0, tree_js_1.current)());
34
+ }
35
+ _a.clearReaders();
36
+ }
37
+ static clearReaders() {
38
+ __classPrivateFieldGet(_a, _a, "f", _Signal_readers).clear();
39
+ }
40
+ static getCurrentReaderWithCursorId(cursor) {
41
+ var _b, _c, _d;
42
+ const callee = (0, tree_js_1.current)();
43
+ (_b = callee === null || callee === void 0 ? void 0 : callee.cursors) === null || _b === void 0 ? void 0 : _b.add(cursor.toString());
44
+ const c = ((_d = (_c = callee === null || callee === void 0 ? void 0 : callee.down) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) - 1;
45
+ return `${callee === null || callee === void 0 ? void 0 : callee.index}.${(c < 0 ? 0 : c).toString()}-${cursor}`;
46
+ }
47
+ static getReadersWithCursor(cursor) {
48
+ return new Set(Array.from(__classPrivateFieldGet(_a, _a, "f", _Signal_readers))
49
+ .filter((r) => r.endsWith(`-${cursor}`))
50
+ .map((v) => v.split("-")[0])
51
+ .filter((v) => v !== undefined));
52
+ }
53
+ static create(initial) {
54
+ const cursor = (0, renderer_js_1.nextCursor)();
55
+ if (!__classPrivateFieldGet(_a, _a, "f", _Signal_memory).has(cursor)) {
56
+ __classPrivateFieldGet(_a, _a, "f", _Signal_memory).set(cursor, { value: initial });
57
+ }
58
+ const state = __classPrivateFieldGet(_a, _a, "f", _Signal_memory).get(cursor);
59
+ const read = () => {
60
+ const reader = _a.getCurrentReaderWithCursorId(cursor);
61
+ if (!__classPrivateFieldGet(_a, _a, "f", _Signal_readers).has(reader)) {
62
+ __classPrivateFieldGet(_a, _a, "f", _Signal_readers).add(reader);
63
+ }
64
+ return state.value;
65
+ };
66
+ const write = (v) => {
67
+ state.value = v;
68
+ (0, scheduler_js_1.rerender)(`${cursor}`, _a.getReadersWithCursor(cursor));
69
+ _a.clearReaders();
70
+ };
71
+ return [read, write];
72
+ }
73
+ }
74
+ exports.Signal = Signal;
75
+ _a = Signal;
76
+ _Signal_memory = { value: new Map() };
77
+ _Signal_readers = { value: new Set() };
@@ -0,0 +1,5 @@
1
+ import type { IComponent } from "./types/component";
2
+ import type { IntrinsicElements } from "./types/html";
3
+ export declare function current(): IComponent<keyof IntrinsicElements>;
4
+ export declare function open(component: IComponent<any>): void;
5
+ export declare function close(): void;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.current = current;
4
+ exports.open = open;
5
+ exports.close = close;
6
+ const stack = [];
7
+ function current() {
8
+ return stack[stack.length - 1];
9
+ }
10
+ function _open(component) {
11
+ stack.push(component);
12
+ }
13
+ function open(component) {
14
+ stack.push(component);
15
+ }
16
+ function close() {
17
+ stack.pop();
18
+ }
@@ -0,0 +1,21 @@
1
+ import type { IntrinsicElements } from "./html.js";
2
+ export type StyleProp<P> = P extends {
3
+ style?: infer ST;
4
+ } ? ST : string | Partial<CSSStyleDeclaration>;
5
+ export interface IComponent<K extends keyof IntrinsicElements> {
6
+ index: string;
7
+ props: IntrinsicElements[K];
8
+ cursors: Set<string>;
9
+ type: K;
10
+ down: IComponent<keyof IntrinsicElements>[];
11
+ up?: IComponent<keyof IntrinsicElements>;
12
+ view?: () => void;
13
+ body(fn: (component: this) => void): this;
14
+ onAppear(fn: (component: this) => void): this;
15
+ withProps<T extends Partial<IntrinsicElements[K]>>(newProps: T): this;
16
+ withStyle(style: StyleProp<IntrinsicElements[K]>): this;
17
+ withExtension(extension: (component: this) => void): this;
18
+ }
19
+ export interface IScreen<K extends keyof IntrinsicElements> extends IComponent<K> {
20
+ render(): void;
21
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,66 @@
1
+ export type EventHandler<E = Event> = (event: E) => void;
2
+ export type CommonProps = {
3
+ id?: string;
4
+ class?: string;
5
+ style?: Partial<CSSStyleDeclaration>;
6
+ title?: string;
7
+ hidden?: boolean;
8
+ onClick?: EventHandler<MouseEvent>;
9
+ onInput?: EventHandler<InputEvent>;
10
+ onChange?: EventHandler<Event>;
11
+ onFocus?: EventHandler<FocusEvent>;
12
+ onBlur?: EventHandler<FocusEvent>;
13
+ onKeyDown?: EventHandler<KeyboardEvent>;
14
+ onKeyUp?: EventHandler<KeyboardEvent>;
15
+ content?: string | number | (() => string | number);
16
+ };
17
+ export type ButtonProps = CommonProps & {
18
+ type?: "button" | "submit" | "reset";
19
+ disabled?: boolean;
20
+ };
21
+ export type InputProps = CommonProps & {
22
+ type?: "text" | "email" | "password" | "number" | "date" | "time" | "datetime-local" | "month" | "week" | "url" | "search" | "tel" | "color";
23
+ value?: string | number;
24
+ placeholder?: string;
25
+ required?: boolean;
26
+ onTextChange?: EventHandler<string>;
27
+ };
28
+ export type SemanticText = {
29
+ h1: CommonProps;
30
+ h2: CommonProps;
31
+ h3: CommonProps;
32
+ h4: CommonProps;
33
+ h5: CommonProps;
34
+ body: CommonProps;
35
+ p: CommonProps;
36
+ span: CommonProps;
37
+ };
38
+ export type IntrinsicElements = {
39
+ root: CommonProps;
40
+ div: CommonProps;
41
+ span: CommonProps;
42
+ semanticText: {
43
+ type: keyof SemanticText;
44
+ props: CommonProps;
45
+ };
46
+ animation: CommonProps;
47
+ button: ButtonProps;
48
+ input: InputProps;
49
+ form: CommonProps;
50
+ label: CommonProps;
51
+ a: CommonProps & {
52
+ href?: string;
53
+ target?: string;
54
+ };
55
+ img: CommonProps & {
56
+ src: string;
57
+ alt?: string;
58
+ };
59
+ textarea: CommonProps & {
60
+ value?: string;
61
+ };
62
+ text: {
63
+ text: string;
64
+ };
65
+ };
66
+ export declare function isCommonProps(props: unknown): props is CommonProps;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isCommonProps = isCommonProps;
4
+ function isObject(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ function isCommonProps(props) {
8
+ if (!isObject(props))
9
+ return false;
10
+ if ("id" in props && typeof props.id !== "string")
11
+ return false;
12
+ if ("class" in props && typeof props.class !== "string")
13
+ return false;
14
+ if ("title" in props && typeof props.title !== "string")
15
+ return false;
16
+ if ("hidden" in props && typeof props.hidden !== "boolean")
17
+ return false;
18
+ if ("content" in props) {
19
+ const c = props.content;
20
+ const valid = typeof c === "string" ||
21
+ typeof c === "number" ||
22
+ typeof c === "function";
23
+ if (!valid)
24
+ return false;
25
+ }
26
+ return true;
27
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./core/elements";
2
+ export * from "./core/scheduler";
3
+ export * from "./core/signals";
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./core/elements"), exports);
18
+ __exportStar(require("./core/scheduler"), exports);
19
+ __exportStar(require("./core/signals"), exports);
package/lefthook.yml ADDED
@@ -0,0 +1,6 @@
1
+ pre-commit:
2
+ commands:
3
+ check:
4
+ glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
5
+ run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
6
+ stage_fixed: true
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "oxiui-lib",
3
+ "version": "0.2.0",
4
+ "module": "src/index.ts",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "biome": "biome format . --write"
11
+ },
12
+ "devDependencies": {
13
+ "@biomejs/biome": "^2.4.4",
14
+ "@types/bun": "latest"
15
+ },
16
+ "peerDependencies": {
17
+ "typescript": "^5.9.3"
18
+ },
19
+ "dependencies": {
20
+ "@types/node": "^25.3.0",
21
+ "lefthook": "^2.1.1"
22
+ }
23
+ }
@@ -0,0 +1,80 @@
1
+ import { intrinsic } from "./OxiComponent.js";
2
+
3
+ export class Animation extends intrinsic("div") {
4
+ #transforms = new Map<string, string>();
5
+
6
+ #applyTransforms() {
7
+ if (this.#transforms.size === 0) {
8
+ this.withStyle({ transform: undefined });
9
+ } else {
10
+ const transformString = Array.from(this.#transforms.values()).join(" ");
11
+ this.withStyle({ transform: transformString });
12
+ }
13
+ }
14
+
15
+ transition(sec: number, type: "ease" | "ease-in-out") {
16
+ this.withStyle({
17
+ transition: `all ${sec}s ${type}`,
18
+ });
19
+ return this;
20
+ }
21
+
22
+ translate(
23
+ direction: "vertical" | "horizontal" | "perpendicular",
24
+ target: number,
25
+ ) {
26
+ let key: string;
27
+ let value: string;
28
+ if (direction === "horizontal") {
29
+ key = "translateX";
30
+ value = `translateX(${target}px)`;
31
+ } else if (direction === "vertical") {
32
+ key = "translateY";
33
+ value = `translateY(${target}px)`;
34
+ } else {
35
+ key = "translateZ";
36
+ value = `translateZ(${target}px)`;
37
+ }
38
+ this.#transforms.set(key, value);
39
+ this.#applyTransforms();
40
+ return this;
41
+ }
42
+
43
+ // Convenience methods
44
+ translateX(target: number) {
45
+ return this.translate("horizontal", target);
46
+ }
47
+
48
+ translateY(target: number) {
49
+ return this.translate("vertical", target);
50
+ }
51
+
52
+ translateZ(target: number) {
53
+ return this.translate("perpendicular", target);
54
+ }
55
+
56
+ rotate(deg: number) {
57
+ this.#transforms.set("rotate", `rotate(${deg}deg)`);
58
+ this.#applyTransforms();
59
+ return this;
60
+ }
61
+
62
+ scale(factor: number) {
63
+ this.#transforms.set("scale", `scale(${factor})`);
64
+ this.#applyTransforms();
65
+ return this;
66
+ }
67
+
68
+ skew(xDeg: number, yDeg?: number) {
69
+ const y = yDeg !== undefined ? yDeg : 0;
70
+ this.#transforms.set("skew", `skew(${xDeg}deg, ${y}deg)`);
71
+ this.#applyTransforms();
72
+ return this;
73
+ }
74
+
75
+ // Optional: manually trigger transform application (useful if you've manipulated the map directly)
76
+ applyTransforms() {
77
+ this.#applyTransforms();
78
+ return this;
79
+ }
80
+ }
@@ -0,0 +1,14 @@
1
+ import type { ButtonProps } from "../types/html.js";
2
+ import { intrinsic } from "./OxiComponent.js";
3
+
4
+ export class Button extends intrinsic("button") {
5
+ constructor(text?: string, props?: ButtonProps) {
6
+ super();
7
+ this.withProps({ content: text ?? props?.content });
8
+ }
9
+
10
+ onClick(callback: () => void): this {
11
+ this.withProps({ onClick: callback });
12
+ return this;
13
+ }
14
+ }
@@ -0,0 +1,8 @@
1
+ import { Stack } from "./Stack.js";
2
+
3
+ export class HRow extends Stack {
4
+ constructor() {
5
+ super();
6
+ this.horizontal().expand();
7
+ }
8
+ }
@@ -0,0 +1,25 @@
1
+ import { intrinsic } from "./OxiComponent.js";
2
+
3
+ export class TextInput extends intrinsic("input") {
4
+ value(value: string | number) {
5
+ this.props.value = value;
6
+ return this;
7
+ }
8
+
9
+ placeholder(text: string) {
10
+ this.props.placeholder = text;
11
+ return this;
12
+ }
13
+
14
+ required(required: boolean = true) {
15
+ this.props.required = required;
16
+ return this;
17
+ }
18
+
19
+ onChangeText(fn: (value: string) => void) {
20
+ this.props.onTextChange = (text: string) => {
21
+ fn(text);
22
+ };
23
+ return this;
24
+ }
25
+ }
@@ -0,0 +1,143 @@
1
+ import { scheduleEffect } from "../scheduler.js";
2
+ import { Signal } from "../signals.js";
3
+ import { close, current, open } from "../tree.js";
4
+ import type { IComponent, StyleProp } from "../types/component.js";
5
+ import type { CommonProps, IntrinsicElements } from "../types/html.js";
6
+
7
+ export class OxiComponent<K extends keyof IntrinsicElements>
8
+ implements IComponent<K>
9
+ {
10
+ #__states = new Map<string | symbol, Signal<unknown>>();
11
+ type: K;
12
+ props: IntrinsicElements[K];
13
+ up?: IComponent<keyof IntrinsicElements>;
14
+ down: IComponent<keyof IntrinsicElements>[] = [];
15
+ cursors: Set<string> = new Set();
16
+ index: string;
17
+ view?: (() => void) | undefined;
18
+
19
+ constructor(type: K, props?: IntrinsicElements[K]) {
20
+ const parent = current() as IComponent<keyof IntrinsicElements> | undefined;
21
+
22
+ this.type = type;
23
+ this.props = props ?? ({} as IntrinsicElements[K]);
24
+ this.up = parent;
25
+
26
+ const position = parent ? parent.down.length : 0;
27
+ this.index = parent ? `${parent.index}.${position}` : "0";
28
+
29
+ parent?.down.push(this as IComponent<K>);
30
+ }
31
+
32
+ body(fn?: (component: this) => void) {
33
+ open(this);
34
+
35
+ if (this.view) {
36
+ this.view();
37
+ } else {
38
+ fn?.(this);
39
+ }
40
+
41
+ close();
42
+ return this;
43
+ }
44
+
45
+ onAppear(fn: (component: this) => void) {
46
+ open(this);
47
+ scheduleEffect(() => fn(this));
48
+ close();
49
+ return this;
50
+ }
51
+
52
+ withProps<T extends Partial<IntrinsicElements[K]>>(newProps: T) {
53
+ open(this);
54
+ this.props = { ...this.props, ...newProps };
55
+ close();
56
+ return this;
57
+ }
58
+
59
+ withStyle(style: StyleProp<IntrinsicElements[K]>) {
60
+ open(this);
61
+
62
+ const currentStyle = (this.props as CommonProps).style;
63
+
64
+ if (typeof style === "object" && typeof currentStyle === "object") {
65
+ this.props = {
66
+ ...this.props,
67
+ style: { ...currentStyle, ...style },
68
+ };
69
+ } else {
70
+ this.props = {
71
+ ...this.props,
72
+ style,
73
+ };
74
+ }
75
+
76
+ close();
77
+ return this;
78
+ }
79
+
80
+ withExtension(extension: (component: this) => void): this {
81
+ open(this);
82
+ extension(this);
83
+ close();
84
+ return this;
85
+ }
86
+
87
+ withState(): this {
88
+ return new Proxy(this, {
89
+ get(target, prop, receiver) {
90
+ if (typeof prop === "string" && prop.startsWith("$")) {
91
+ let signal = target.#__states.get(prop);
92
+
93
+ if (!signal) {
94
+ open(target);
95
+ signal = new Signal(Reflect.get(target, prop, receiver));
96
+ target.#__states.set(prop, signal);
97
+ close();
98
+ }
99
+
100
+ return signal.value;
101
+ }
102
+
103
+ return Reflect.get(target, prop, receiver);
104
+ },
105
+
106
+ set(target, prop, value, receiver) {
107
+ if (typeof prop === "string" && prop.startsWith("$")) {
108
+ let signal = target.#__states.get(prop);
109
+
110
+ open(target);
111
+ if (!signal) {
112
+ signal = new Signal(value);
113
+ target.#__states.set(prop, signal);
114
+ } else {
115
+ signal.value = value;
116
+ }
117
+ close();
118
+ return true;
119
+ }
120
+
121
+ return Reflect.set(target, prop, value, receiver);
122
+ },
123
+ }) as this;
124
+ }
125
+ }
126
+
127
+ export function intrinsic<K extends keyof IntrinsicElements>(type: K) {
128
+ return class extends OxiComponent<K> {
129
+ constructor(props?: IntrinsicElements[K]) {
130
+ super(type, props);
131
+ }
132
+ };
133
+ }
134
+
135
+ export function intrinsicState<K extends keyof IntrinsicElements>(type: K) {
136
+ return class extends OxiComponent<K> {
137
+ constructor(props?: IntrinsicElements[K]) {
138
+ super(type, props);
139
+ // biome-ignore lint: correctness/noConstructorReturn
140
+ return this.withState();
141
+ }
142
+ };
143
+ }
@@ -0,0 +1,3 @@
1
+ import { intrinsic } from "./OxiComponent.js";
2
+
3
+ export class DivContainer extends intrinsic("div") {}
@@ -0,0 +1,44 @@
1
+ import { intrinsic } from "./OxiComponent.js";
2
+
3
+ export class Stack extends intrinsic("div") {
4
+ constructor() {
5
+ super();
6
+ this.withStyle({
7
+ display: "flex",
8
+ });
9
+ }
10
+
11
+ verticalAlignment(value: "top" | "center" | "bottom"): this {
12
+ return this.withStyle({
13
+ alignItems:
14
+ value === "top"
15
+ ? "flex-start"
16
+ : value === "center"
17
+ ? "center"
18
+ : "flex-end",
19
+ });
20
+ }
21
+
22
+ horizontalAlignment(value: "left" | "center" | "right"): this {
23
+ return this.withStyle({
24
+ justifyContent:
25
+ value === "left"
26
+ ? "flex-start"
27
+ : value === "center"
28
+ ? "center"
29
+ : "flex-end",
30
+ });
31
+ }
32
+
33
+ expand(): this {
34
+ return this.withStyle({ flex: "1" });
35
+ }
36
+
37
+ horizontal(): this {
38
+ return this.withStyle({ flexDirection: "row" });
39
+ }
40
+
41
+ vertical(): this {
42
+ return this.withStyle({ flexDirection: "column" });
43
+ }
44
+ }
@@ -0,0 +1,53 @@
1
+ import type { SemanticText } from "../types/html.js";
2
+ import { intrinsic } from "./OxiComponent.js";
3
+
4
+ export class Text extends intrinsic("semanticText") {
5
+ constructor(text: string | number | (() => string | number)) {
6
+ super();
7
+
8
+ this.props = {
9
+ type: "span",
10
+ props: {
11
+ content: text,
12
+ },
13
+ };
14
+ }
15
+
16
+ override withStyle(style: string | Partial<CSSStyleDeclaration>): this {
17
+ this.props.props.style = style;
18
+ return this;
19
+ }
20
+
21
+ private setType(type: keyof SemanticText) {
22
+ this.props.type = type;
23
+ return this;
24
+ }
25
+
26
+ asTitle() {
27
+ return this.setType("h1");
28
+ }
29
+
30
+ asSubtitle() {
31
+ return this.setType("h2");
32
+ }
33
+
34
+ asH3() {
35
+ return this.setType("h3");
36
+ }
37
+
38
+ asH4() {
39
+ return this.setType("h4");
40
+ }
41
+
42
+ asH5() {
43
+ return this.setType("h5");
44
+ }
45
+
46
+ asBody() {
47
+ return this.setType("body");
48
+ }
49
+
50
+ asParagraph() {
51
+ return this.setType("p");
52
+ }
53
+ }
@@ -0,0 +1,8 @@
1
+ import { Stack } from "./Stack.js";
2
+
3
+ export class VRow extends Stack {
4
+ constructor() {
5
+ super();
6
+ this.vertical().expand();
7
+ }
8
+ }