paintcannon-react 0.0.41 → 0.0.43
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/README.md +11 -0
- package/dist/src/host-components/a/a.d.ts +8 -0
- package/dist/src/host-components/a/a.js +3 -0
- package/dist/src/host-components/a/reconcile-a.d.ts +6 -0
- package/dist/src/host-components/a/reconcile-a.js +13 -0
- package/dist/src/host-components/index.d.ts +2 -0
- package/dist/src/host-components/index.js +2 -0
- package/dist/src/host-components/mounted.d.ts +4 -2
- package/dist/src/host-components/mounted.js +2 -0
- package/dist/src/host-components/reconcile-shared.d.ts +1 -1
- package/dist/src/host-components/reconcile-shared.js +1 -4
- package/dist/src/host-components/shared.d.ts +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +1 -0
- package/dist/src/reconciler.js +13 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -88,6 +88,7 @@ DOM API:
|
|
|
88
88
|
|
|
89
89
|
- `Div`
|
|
90
90
|
- `Span`
|
|
91
|
+
- `A`
|
|
91
92
|
- `Input`
|
|
92
93
|
- `Textarea`
|
|
93
94
|
- `Button`
|
|
@@ -112,6 +113,15 @@ app.paintCannon.addEventListener("blur", () => {
|
|
|
112
113
|
|
|
113
114
|
Inside tmux, terminal focus reporting requires `set -g focus-events on`.
|
|
114
115
|
|
|
116
|
+
Font capabilities are available through `app.paintCannon.font`. Use
|
|
117
|
+
`hasNerdFontSet(set)` or `hasSymbolsForLegacyComputing()` for initial support,
|
|
118
|
+
then subscribe with `font.addEventListener("nerdfont-powerline-change", listener)`
|
|
119
|
+
or `"symbols-for-legacy-computing-change"` to update React state from
|
|
120
|
+
`event.supported`. Remove the listener in your effect's cleanup. Rust refreshes
|
|
121
|
+
support every two seconds, requires support in every attached tmux terminal
|
|
122
|
+
client, and repaints chunky borders automatically. See [font detection in
|
|
123
|
+
PaintCannon](../paintcannon/README.md#nerd-font-detection) for all sets and limits.
|
|
124
|
+
|
|
115
125
|
### Common props:
|
|
116
126
|
|
|
117
127
|
All host components accept:
|
|
@@ -227,6 +237,7 @@ both supported:
|
|
|
227
237
|
|
|
228
238
|
- `Div`: shared props, plus `scrollLeft?: number` and `scrollTop?: number`.
|
|
229
239
|
- `Span`: shared props, plus `scrollLeft?: number` and `scrollTop?: number`.
|
|
240
|
+
- `A`: shared props, `scrollLeft?: number`, `scrollTop?: number`, and `href?: string`.
|
|
230
241
|
- `Form`: shared props, plus `scrollLeft?: number` and `scrollTop?: number`.
|
|
231
242
|
- `Button`: shared props, plus `type?: "submit" | "button"`,
|
|
232
243
|
`scrollLeft?: number`, and `scrollTop?: number`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AnchorElement } from "paintcannon";
|
|
2
|
+
import type { CommonProps, HostComponent, Scrollable } from "../shared.ts";
|
|
3
|
+
export type Props = CommonProps & Partial<Scrollable> & {
|
|
4
|
+
href?: string;
|
|
5
|
+
};
|
|
6
|
+
export type Element = AnchorElement;
|
|
7
|
+
export declare const type: "paintcannon.a";
|
|
8
|
+
export declare const Component: HostComponent<Props, Element>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PaintCannon } from "paintcannon";
|
|
2
|
+
import * as a from "./a.ts";
|
|
3
|
+
import type { MountedComponent } from "../mounted.ts";
|
|
4
|
+
import { type ApplyCommonProps } from "../reconcile-shared.ts";
|
|
5
|
+
export declare function create(paintCannon: PaintCannon, props: a.Props, applyCommonProps: ApplyCommonProps): MountedComponent<typeof a>;
|
|
6
|
+
export declare function applyProps(node: a.Element, oldProps: Partial<a.Props>, newProps: a.Props, applyCommonProps: ApplyCommonProps): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as a from "./a.js";
|
|
2
|
+
import { applyScrollableElementProps } from "../reconcile-shared.js";
|
|
3
|
+
export function create(paintCannon, props, applyCommonProps) {
|
|
4
|
+
const node = paintCannon.createElement("a");
|
|
5
|
+
applyProps(node, {}, props, applyCommonProps);
|
|
6
|
+
return { kind: "element", type: a.type, props, children: new Set(), node };
|
|
7
|
+
}
|
|
8
|
+
export function applyProps(node, oldProps, newProps, applyCommonProps) {
|
|
9
|
+
applyScrollableElementProps(node, oldProps, newProps, applyCommonProps);
|
|
10
|
+
if (oldProps.href !== newProps.href) {
|
|
11
|
+
node.href = newProps.href ?? "";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -12,3 +12,5 @@ export * as reconcileSpan from "./span/reconcile-span.ts";
|
|
|
12
12
|
export * as reconcileTextarea from "./textarea/reconcile-textarea.ts";
|
|
13
13
|
export * as span from "./span/span.ts";
|
|
14
14
|
export * as textarea from "./textarea/textarea.ts";
|
|
15
|
+
export * as a from "./a/a.ts";
|
|
16
|
+
export * as reconcileA from "./a/reconcile-a.ts";
|
|
@@ -12,3 +12,5 @@ export * as reconcileSpan from "./span/reconcile-span.js";
|
|
|
12
12
|
export * as reconcileTextarea from "./textarea/reconcile-textarea.js";
|
|
13
13
|
export * as span from "./span/span.js";
|
|
14
14
|
export * as textarea from "./textarea/textarea.js";
|
|
15
|
+
export * as a from "./a/a.js";
|
|
16
|
+
export * as reconcileA from "./a/reconcile-a.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PaintElement, TextNode } from "paintcannon";
|
|
2
|
+
import * as a from "./a/a.ts";
|
|
2
3
|
import * as button from "./button/button.ts";
|
|
3
4
|
import * as div from "./div/div.ts";
|
|
4
5
|
import * as form from "./form/form.ts";
|
|
@@ -6,7 +7,7 @@ import * as input from "./input/input.ts";
|
|
|
6
7
|
import * as span from "./span/span.ts";
|
|
7
8
|
import * as textarea from "./textarea/textarea.ts";
|
|
8
9
|
import type { HostComponent, HostType } from "./shared.ts";
|
|
9
|
-
export type HostProps = div.Props | span.Props | form.Props | button.Props | input.Props | textarea.Props;
|
|
10
|
+
export type HostProps = a.Props | div.Props | span.Props | form.Props | button.Props | input.Props | textarea.Props;
|
|
10
11
|
export type MountedHostElement<Type extends HostType, Props, Element extends PaintElement> = {
|
|
11
12
|
kind: "element";
|
|
12
13
|
type: Type;
|
|
@@ -19,7 +20,7 @@ export type MountedComponent<Module> = Module extends {
|
|
|
19
20
|
type: infer Type extends HostType;
|
|
20
21
|
Component: HostComponent<infer Props, infer Element extends PaintElement>;
|
|
21
22
|
} ? MountedHostElement<Type, Props, Element> : never;
|
|
22
|
-
export type HostElement = MountedComponent<typeof div> | MountedComponent<typeof span> | MountedComponent<typeof form> | MountedComponent<typeof button> | MountedComponent<typeof input> | MountedComponent<typeof textarea>;
|
|
23
|
+
export type HostElement = MountedComponent<typeof a> | MountedComponent<typeof div> | MountedComponent<typeof span> | MountedComponent<typeof form> | MountedComponent<typeof button> | MountedComponent<typeof input> | MountedComponent<typeof textarea>;
|
|
23
24
|
export type HostText = {
|
|
24
25
|
kind: "text";
|
|
25
26
|
text: string;
|
|
@@ -31,6 +32,7 @@ export type HostParent = {
|
|
|
31
32
|
children: Set<HostNode>;
|
|
32
33
|
};
|
|
33
34
|
declare const hostPropsForType: {
|
|
35
|
+
"paintcannon.a": a.Props;
|
|
34
36
|
"paintcannon.div": div.Props;
|
|
35
37
|
"paintcannon.span": span.Props;
|
|
36
38
|
"paintcannon.form": form.Props;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as a from "./a/a.js";
|
|
1
2
|
import * as button from "./button/button.js";
|
|
2
3
|
import * as div from "./div/div.js";
|
|
3
4
|
import * as form from "./form/form.js";
|
|
@@ -5,6 +6,7 @@ import * as input from "./input/input.js";
|
|
|
5
6
|
import * as span from "./span/span.js";
|
|
6
7
|
import * as textarea from "./textarea/textarea.js";
|
|
7
8
|
const hostPropsForType = {
|
|
9
|
+
[a.type]: undefined,
|
|
8
10
|
[div.type]: undefined,
|
|
9
11
|
[span.type]: undefined,
|
|
10
12
|
[form.type]: undefined,
|
|
@@ -5,4 +5,4 @@ import type { CommonProps, Scrollable } from "./shared.ts";
|
|
|
5
5
|
export type ApplyCommonProps = (node: PaintElement, oldProps: Partial<CommonProps>, newProps: CommonProps) => void;
|
|
6
6
|
export declare function applyScrollableElementProps<Props extends CommonProps & Partial<Scrollable>>(node: PaintElement & Scrollable, oldProps: Partial<Props>, newProps: Props, applyCommonProps: ApplyCommonProps): void;
|
|
7
7
|
export declare function applyScrollableProps(node: Scrollable, props: Partial<Scrollable>): void;
|
|
8
|
-
export declare function applyTextControlProps<T extends InputElement | TextAreaElement>(node: T,
|
|
8
|
+
export declare function applyTextControlProps<T extends InputElement | TextAreaElement>(node: T, _oldProps: Partial<input.Props | textarea.Props>, newProps: input.Props | textarea.Props): void;
|
|
@@ -10,7 +10,7 @@ export function applyScrollableProps(node, props) {
|
|
|
10
10
|
node.scrollTop = props.scrollTop;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
export function applyTextControlProps(node,
|
|
13
|
+
export function applyTextControlProps(node, _oldProps, newProps) {
|
|
14
14
|
if (newProps.value !== undefined) {
|
|
15
15
|
node.value = newProps.value;
|
|
16
16
|
}
|
|
@@ -20,7 +20,4 @@ export function applyTextControlProps(node, oldProps, newProps) {
|
|
|
20
20
|
if (newProps.cursorPosition !== undefined) {
|
|
21
21
|
node.cursorPosition = newProps.cursorPosition;
|
|
22
22
|
}
|
|
23
|
-
if (newProps.autoFocus === true && oldProps.autoFocus !== true) {
|
|
24
|
-
node.focus();
|
|
25
|
-
}
|
|
26
23
|
}
|
|
@@ -31,11 +31,11 @@ type ElementEventProps = {
|
|
|
31
31
|
export type CommonProps = ElementEventProps & {
|
|
32
32
|
children?: React.ReactNode;
|
|
33
33
|
style?: CSSStyleProperties;
|
|
34
|
+
autoFocus?: boolean;
|
|
34
35
|
};
|
|
35
36
|
export type TextControlProps = CommonProps & {
|
|
36
37
|
value?: string;
|
|
37
38
|
placeholder?: string;
|
|
38
39
|
cursorPosition?: number;
|
|
39
|
-
autoFocus?: boolean;
|
|
40
40
|
};
|
|
41
41
|
export {};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -19,3 +19,6 @@ export declare const Input: hostComponents.HostComponent<hostComponents.input.Pr
|
|
|
19
19
|
export type TextareaProps = hostComponents.textarea.Props;
|
|
20
20
|
export type TextareaElement = hostComponents.textarea.Element;
|
|
21
21
|
export declare const Textarea: hostComponents.HostComponent<hostComponents.textarea.Props, import("paintcannon").TextAreaElement>;
|
|
22
|
+
export type AProps = hostComponents.a.Props;
|
|
23
|
+
export type AnchorElement = hostComponents.a.Element;
|
|
24
|
+
export declare const A: hostComponents.HostComponent<hostComponents.a.Props, import("paintcannon").AnchorElement>;
|
package/dist/src/index.js
CHANGED
package/dist/src/reconciler.js
CHANGED
|
@@ -70,7 +70,10 @@ const reconciler = createReconciler({
|
|
|
70
70
|
removeVirtualChild(container, child);
|
|
71
71
|
destroyHostNode(child);
|
|
72
72
|
},
|
|
73
|
-
finalizeInitialChildren: () =>
|
|
73
|
+
finalizeInitialChildren: (_instance, _type, props) => props.autoFocus === true,
|
|
74
|
+
commitMount(instance) {
|
|
75
|
+
instance.node.focus();
|
|
76
|
+
},
|
|
74
77
|
resetTextContent: () => { },
|
|
75
78
|
getPublicInstance(instance) {
|
|
76
79
|
return instance.node;
|
|
@@ -229,6 +232,9 @@ function createHostElement(paintCannon, type, props) {
|
|
|
229
232
|
if (type === hostComponents.div.type) {
|
|
230
233
|
return hostComponents.reconcileDiv.create(paintCannon, hostComponents.castHostProps(type, props), applyCommonProps);
|
|
231
234
|
}
|
|
235
|
+
if (type === hostComponents.a.type) {
|
|
236
|
+
return hostComponents.reconcileA.create(paintCannon, hostComponents.castHostProps(type, props), applyCommonProps);
|
|
237
|
+
}
|
|
232
238
|
if (type === hostComponents.span.type) {
|
|
233
239
|
return hostComponents.reconcileSpan.create(paintCannon, hostComponents.castHostProps(type, props), applyCommonProps);
|
|
234
240
|
}
|
|
@@ -268,6 +274,11 @@ function applyHostElementProps(host, newProps) {
|
|
|
268
274
|
hostComponents.reconcileDiv.applyProps(host.node, host.props, props, applyCommonProps);
|
|
269
275
|
return props;
|
|
270
276
|
}
|
|
277
|
+
if (host.type === hostComponents.a.type) {
|
|
278
|
+
const props = hostComponents.castHostProps(host.type, newProps);
|
|
279
|
+
hostComponents.reconcileA.applyProps(host.node, host.props, props, applyCommonProps);
|
|
280
|
+
return props;
|
|
281
|
+
}
|
|
271
282
|
if (host.type === hostComponents.span.type) {
|
|
272
283
|
const props = hostComponents.castHostProps(host.type, newProps);
|
|
273
284
|
hostComponents.reconcileSpan.applyProps(host.node, host.props, props, applyCommonProps);
|
|
@@ -359,7 +370,7 @@ function reactEventListener(listener) {
|
|
|
359
370
|
return wrapped;
|
|
360
371
|
}
|
|
361
372
|
function defaultDisplay(type) {
|
|
362
|
-
return type === hostComponents.span.type ? "inline" : "block";
|
|
373
|
+
return type === hostComponents.span.type || type === hostComponents.a.type ? "inline" : "block";
|
|
363
374
|
}
|
|
364
375
|
function reportReactError(error) {
|
|
365
376
|
if (error !== null && error !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paintcannon-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.43",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"build": "tsc",
|
|
24
24
|
"demo": "npm run build && node dist/examples/counter.js",
|
|
25
25
|
"demo:controlled": "npm run build && node dist/examples/controlled.js",
|
|
26
|
+
"demo:emoji-width": "npm run build && node dist/examples/emoji-width.js",
|
|
26
27
|
"demo:form": "npm run build && node dist/examples/form.js",
|
|
27
28
|
"demo:keyboard": "npm run build && node dist/examples/keyboard.js",
|
|
28
29
|
"demo:lifecycle": "npm run build && node dist/examples/lifecycle.js",
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
"scheduler": "^0.25.0"
|
|
37
38
|
},
|
|
38
39
|
"peerDependencies": {
|
|
39
|
-
"paintcannon": "^0.0.
|
|
40
|
+
"paintcannon": "^0.0.43",
|
|
40
41
|
"react": "^19.0.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|